mysql limit inside group?

后端 未结 8 656
粉色の甜心
粉色の甜心 2021-01-13 07:35

I want to limit the size of records inside a group, and here is my trial, how to do it right?

mysql> select * from accounts limit 5 group by type;
         


        
相关标签:
8条回答
  • 2021-01-13 07:36

    I am not sure you can use a limit in the group by. You can probably use it if your group by is a sub select that returns one row/value. For example:

    select * from foo order by (select foo2.id from foo2 limit 1)

    I am just guessing this would work.

    0 讨论(0)
  • 2021-01-13 07:41

    It appears you want to limit the number of rows returned within each group of your overall result set... this is difficult to do in a way that scales well. One technique is to perform N joins on the same table with the conditions such that the only rows that match are the top/bottom N that you want.

    this page may offer some additional insight into your solution... although returning the top 5 in each group is going to get ugly fast.

    0 讨论(0)
  • 2021-01-13 07:41

    @dnagirl's answer almost has it, but for some reason, my version of MySQL only returns the first LIMIT'd set. To get around that, I put each statement into a subquery

    SELECT * FROM (
        SELECT account_type, account_balance FROM accounts WHERE account_type='savings' 
           ORDER BY account_balance DESC LIMIT 5
    ) as a
    UNION
    SELECT* FROM (
        SELECT account_type, account_balance FROM accounts WHERE account_type='chequing' 
           ORDER BY account_balance DESC LIMIT 5
    ) as b
    UNION
    SELECT * FROM (
        SELECT account_type, account_balance FROM accounts WHERE account_type='USD' 
           ORDER BY account_balance DESC LIMIT 5
    ) as c
    

    This gave me back each set's results in the final result set. Otherwise, I would have only gotten the first 5 from the first query and nothing else - not sure if it's just some MySQL funk with my version

    0 讨论(0)
  • 2021-01-13 07:47

    The point of an aggregate function (and the GROUP BY it requires) is to turn many rows into one row. So if you really just want the top 5 savings accounts and the top 5 chequing accounts and the top 5 USD accounts etc., what you need is more like this:

    criteria: top 5 of particular account type by account_balance

    SELECT account_type, account_balance FROM accounts WHERE account_type='savings' 
       ORDER BY account_balance DESC LIMIT 5
    UNION
    SELECT account_type, account_balance FROM accounts WHERE account_type='chequing' 
       ORDER BY account_balance DESC LIMIT 5
    UNION
    SELECT account_type, account_balance FROM accounts WHERE account_type='USD' 
       ORDER BY account_balance DESC LIMIT 5;
    

    It's not pretty, but if you construct the SQL with a script then subbing in the account_types and concatenating together a query is straightforward.

    0 讨论(0)
  • 2021-01-13 07:56

    Try placing the LIMIT clause after the GROUP BY clause.

    EDIT: Try this:

    SELECT * 
    FROM accounts a1
    WHERE 5 > 
    (
       SELECT COUNT(*)
       FROM accounts a2
       WHERE a2.type = a1.type
       AND a2.balance > a1.balance
    )
    

    This returns at most 5 accounts of each type with the biggest balances.

    0 讨论(0)
  • 2021-01-13 07:58

    I've had some luck with using numbered rows:

    set @type = '';
    set @num = 0;
    
    select
      items.*,
      @num := if(@type = item_type, @num + 1, 1) as dummy_1,
      @type := item_type as dummy_2,
      @num as row_number
    from items
    group by
      item_type,
      row_number
    having row_number < 3;
    

    This will give you 2 results per item_type. (One gotcha: make sure you re-run the first two set statements otherwise your row numbers will steadily get higher and higher and the row_number < 3 restriction won't work.

    I pieced this together from a couple of posts which have been linked in other answers on SO.

    0 讨论(0)
提交回复
热议问题