phpmysqldatabasesubquerydynamic-queries

Using LIMIT within GROUP BY to get N results per dynamic group


Using LIMIT within GROUP BY to get N results per dynamic group

Hello everyone, firstly I read about questions like this problem. But didn't get the solution. All of this SQL's are designed for static columns. But I have dynamic columns.

Table:

id  Name      Group Level 
2   Jonathan  A     5 
5   David     A     10
6   Alex      C     10
7   Kemal     A     71
8   John      D     21
9   Celin     F     100
12  Alexis    G     15
13  Noone     A     23

I want to get the first 2 highest Level from each group.

But query must be dynamic because there will be more Groups, which is where I am stuck.

Solutions I tried:

  1. Select the top N rows from each group Not giving true result it's broken.
  2. Only work in static columns.

Solution

  • DROP TABLE IF EXISTS my_table;
    
    CREATE TABLE my_table
    (id SERIAL PRIMARY KEY
    ,name VARCHAR(12) NOT NULL
    ,group_name CHAR(1) NOT NULL
    ,level INT NOT NULL
    );
    
    INSERT INTO my_table VALUES
    ( 2,'Jonathan','A',5),
    ( 5,'David','A',10),
    ( 6,'Alex','C',10),
    ( 7,'Kemal','A',71),
    ( 8,'John','D',21),
    ( 9,'Celin','F',100),
    (12,'Alexis','G',15),
    (13,'Noone','A',23);
    
    SELECT id
         , name
         , group_name
         , level 
      FROM 
         ( SELECT x.*
                , CASE WHEN @prev = group_name THEN @i:=@i+1 ELSE @i:=1 END i
                , @prev:=group_name 
             FROM my_table x -- technically, ordering should really happen here, in a separate subquery
                , ( SELECT @prev:=null,@i:=0 ) vars 
            ORDER 
               BY group_name
                , level DESC
                , id
         ) a 
     WHERE i <=2;
    +----+--------+------------+-------+
    | id | name   | group_name | level |
    +----+--------+------------+-------+
    |  7 | Kemal  | A          |    71 |
    | 13 | Noone  | A          |    23 |
    |  6 | Alex   | C          |    10 |
    |  8 | John   | D          |    21 |
    |  9 | Celin  | F          |   100 |
    | 12 | Alexis | G          |    15 |
    +----+--------+------------+-------+