GROUP BY and individual order

I read the MySQL answers in order before group on , but applying it to my query ends with a subquery in the subquery for a fairly simple case, so I wonder if this can be simplified:

Pattern with sample data

For brevity, I omitted the other fields in the table members. In addition, many more tables have been added to the real application, but they are simply combined. This is a table membership_stackthat gives me problems.

CREATE TABLE members (
  id int unsigned auto_increment,
  first_name varchar(255) not null,
  PRIMARY KEY(id)
);

INSERT INTO members (id, first_name)
     VALUES (1, 'Tyler'),
            (2, 'Marissa'),
            (3, 'Alex'),
            (4, 'Parker');

CREATE TABLE membership_stack (
  id int unsigned auto_increment,
  member_id int unsigned not null,
  sequence int unsigned not null,
  team varchar(255) not null,
  `status` varchar(255) not null,
  PRIMARY KEY(id),
  FOREIGN KEY(member_id) REFERENCES members(id)
);

-- Algorithm to determine correct team:
-- 1. Only consider rows with the highest sequence number
-- 2. Order statuses and pick the first one found:
--    (active, completed, cancelled, abandoned)

INSERT INTO membership_stack (member_id, sequence, team, status)
     VALUES (1, 1, 'instinct', 'active'),
            (1, 1, 'valor', 'abandoned'),
            (2, 1, 'valor', 'active'),
            (2, 2, 'mystic', 'abandoned'),
            (2, 2, 'valor', 'completed'),
            (3, 1, 'instinct', 'completed'),
            (3, 2, 'valor', 'active');

I cannot change the database schema because the data is synchronized with an external data source.

Query

This is what I still have:

    SELECT m.id, m.first_name, ms.sequence, ms.team, ms.status
      FROM membership_stack AS ms
      JOIN (
    SELECT member_id, MAX(sequence) AS sequence
      FROM membership_stack
  GROUP BY member_id
           ) AS t1
        ON ms.member_id = t1.member_id
       AND ms.sequence = t1.sequence
RIGHT JOIN members AS m
        ON ms.member_id = m.id
  ORDER BY m.id, FIELD(ms.status, 'active', 'completed', 'cancelled', 'abandoned');

, , , " " . , , - id .

:

| id | first_name | sequence |     team |    status |
|----|------------|----------|----------|-----------|
|  1 |      Tyler |        1 | instinct |    active |
|  2 |    Marissa |        2 |    valor | completed |
|  3 |       Alex |        2 |    valor |    active |
|  4 |     Parker |     NULL |     NULL |      NULL |

?

: , - . . , .

+4
2

WHERE LIMIT 1:

SELECT m.id, m.first_name, ms.sequence, ms.team, ms.status
FROM members AS m
JOIN membership_stack AS ms ON ms.member_id = m.id
WHERE ms.id = (
    SELECT ms1.id
    FROM membership_stack AS ms1
    WHERE ms1.member_id = ms.member_id
    ORDER BY ms1.sequence desc, 
             FIELD(ms1.status, 'active', 'completed', 'cancelled', 'abandoned'),
             ms1.id asc
    LIMIT 1
)
ORDER BY m.id;

: http://rextester.com/HGU18448

, membership_stack, LEFT JOIN WHERE ON:

SELECT m.id, m.first_name, ms.sequence, ms.team, ms.status
FROM members AS m
LEFT JOIN membership_stack AS ms 
    ON  ms.member_id = m.id
    AND ms.id = (
        SELECT ms1.id
        FROM membership_stack AS ms1
        WHERE ms1.member_id = ms.member_id
        ORDER BY ms1.sequence desc, 
                 FIELD(ms1.status, 'active', 'completed', 'cancelled', 'abandoned'),
                 ms1.id asc
        LIMIT 1
    )
ORDER BY m.id;

: http://rextester.com/NPI79503

0

.

membership_stack, . . join members .

select ms.*
from (select ms.*,
             (@rn := if(@m = member_id, @rn + 1,
                        if(@m := member_id, 1, 1)
                       )
             ) as rn
      from membership_stack ms cross join
           (select @m := -1, @rn := 0) params
      order by member_id, sequence desc,
               field(ms.status, 'active', 'completed', 'cancelled', 'abandoned')
     ) ms
where rn = 1;

- . .

EDIT:

MySQL LIMIT. , :

select ms.*
from membership_stack ms
where (sequence, status) = (select ms2.sequence, ms2.status
                            from membership_stack ms2
                            where ms2.member_id = ms.member_id
                            order by ms2.member_id, ms2.sequence desc,
                                     field(ms2.status, 'active', 'completed', 'cancelled', 'abandoned')
                            limit 1
                           );
0

Source: https://habr.com/ru/post/1672071/


All Articles