What is the best way to select the first two records of each group by a “SELECT” command?

后端 未结 3 717
别跟我提以往
别跟我提以往 2021-02-10 05:30

For instance I have the following table:

id group data
1 1 aaa
2 1 aaa
3 2 aaa
4 2 aaa
5 2 aaa
6 3 aaa
7 3 aaa
8 3 aaa

What is the best way to

相关标签:
3条回答
  • 2021-02-10 05:49

    You select, filter and order your query like normal and then

    for MSSQL

    SELECT TOP 2 * FROM foo; 
    

    From what I can remember Sybase, Oracle and possible a few other RDBMS's uses this syntax to.

    for MySQL you do

    SELECT * FROM foo LIMIT 2; 
    

    Update:

    Yes, I misread your question, sorry. Seems like a few of us did :)

    Then it depends on whether you RDBMS supports HAVING or not etc. You could construct a query using HAVING or using IN and a subquery in the IN clause.

    For MSSQL I think you could do something like (code not tested)

    SELECT id, data
        FROM (
            SELECT id, data, Rank() over (Partition BY group ORDER BY id DESC ) AS Rank
            FROM table
            ) rs WHERE Rank <= 2)
    

    But since this depends on your RDBMS I ask you to look at similar questions and see which one works best for your case since MSSQL supports some things MySQL doesn't and the other way around.

    Here are some examples

    Select top 10 records for each category

    How to select the last two records for each topic_id in MySQL

    0 讨论(0)
  • 2021-02-10 05:50
    select a.*
    from Tablename a
    where 
    (
       select count(*) 
       from Tablename as b
       where a.group = b.group and a.id >= b.id
    ) <= 2
    
    • SQLFiddle Demo
    0 讨论(0)
  • 2021-02-10 05:51

    I like this trick, that makes use of GROUP_CONCAT aggregate function, and FIND_IN_SET:

    SELECT
      Tablename.*
    FROM
      Tablename INNER JOIN (
        SELECT `group`, GROUP_CONCAT(id ORDER BY id) ids
        FROM Tablename
        GROUP BY `group`) grp ON
      Tablename.`group` = grp.`group` AND
      FIND_IN_SET(Tablename.id, ids)<=2
    ORDER BY
      Tablename.`group`, Tablename.id
    

    Performances can't be too good, as it can't make use of an index.

    Or you can also use this:

    SELECT t1.id, t1.`group`, t1.data
    from
      Tablename t1 INNER JOIN Tablename t2
      ON t1.`group` = t2.`group` AND t1.id>=t2.id
    GROUP BY
      t1.id, t1.`group`, t1.data
    HAVING
      COUNT(*)<=2
    ORDER BY
      t1.`group`, t1.id, t1.data
    
    0 讨论(0)
提交回复
热议问题