[MySQL] grouping and sorting: obtain the first N records and generate an automatic number sequence, similar to group by after limit, mysqlgroup

Source: Internet
Author: User

[MySQL] grouping and sorting: obtain the first N records and generate an automatic number sequence, similar to group by after limit, mysqlgroup

Preface:

The business scenario of a colleague is to group by cid and author, and then reverse the id to retrieve the first two records.

In oracle, row_number () OVER (partition by cid, author order by id DESC) can be used to indicate the group based on cid and author, and the group is sorted BY id within the group, the value calculated by this function indicates the sequential numbers after sorting in each group (the sequential and unique in the group), and the mysql database does not have such a statistical function, you need to write complex SQL statements for implementation.


1. input test data

  1. USE csdn;
  2. Drop table if exists test;
  3. Create table test (
  4. Id int primary key,
  5. Cid INT,
  6. Author VARCHAR (30)
  7. ) ENGINE = INNODB;


  8. Insert into test VALUES
  9. (1, 1, \ 'test1 \'),
  10. (2, 1, \ 'test1 \'),
  11. (3,1, \ 'test2 \'),
  12. (4,1, \ 'test2 \'),
  13. (5, 1, \ 'test2 \'),
  14. (6, 1, \ 'test3 \'),
  15. (7,1, \ 'test3 \'),
  16. (8, 1, \ 'test3 \'),
  17. (9,1, \ 'test3 \'),
  18. (10, 2, \ 'test11 \'),
  19. (11,2, \ 'test11 \'),
  20. (12, 2, \ 'test22 \'),
  21. (13,2, \ 'test22 \'),
  22. (14,2, \ 'test22 \'),
  23. (15,2, \ 'test33 \'),
  24. (16,2, \ 'test33 \'),
  25. (17,2, \ 'test33 \'),
  26. (18,2, \ 'test33 \');
  27. Insert into test valuees (200,200, \ '200test _ nagios \');

2. Original low-efficiency subquery implementation methods
The SQL code is as follows:


  1. SELECT * FROM test
  2. WHERE
  3. N> (
  4. Select count (*)
  5. FROM test B
  6. WHERE a. cid = B. cid AND a. 'author' = B. 'author' AND a. id <B. id
  7. ) Order by cid, author, id DESC;

If you replace N with a number such as 2, the first two records of each group are queried, as shown below:

  1. Mysql> SELECT * FROM test
  2. -> WHERE
  3. -> 2> (
  4. -> Select count (*)
  5. -> FROM test B
  6. -> WHERE a. cid = B. cid AND a. 'author' = B. 'author' AND a. id <B. id
  7. ->) Order by cid, author, id DESC;
  8. + ----- + ------ + ---------------- +
  9. | Id | cid | author |
  10. + ----- + ------ + ---------------- +
  11. | 2 | 1 | test1 |
  12. | 1 | 1 | test1 |
  13. | 5 | 1 | test2 |
  14. | 4 | 1 | test2 |
  15. | 9 | 1 | test3 |
  16. | 8 | 1 | test3 |
  17. | 11 | 2 | test11 |
  18. | 10 | 2 | test11 |
  19. | 14 | 2 | test22 |
  20. | 13 | 2 | test22 |
  21. | 18 | 2 | test33 |
  22. | 17 | 2 | test33 |
  23. | 200 | 200 | 200test_nagios |
  24. + ----- + ------ + ---------------- +
  25. 13 rows in set (0.00 sec)


  26. Mysql>


3. Use dynamic SQL
First, construct the serial number and introduce a @ row for rownumber.
SET @ row = 0; SET @ mid = ''; SELECT cid, author, @ row: = @ row + 1 rownum FROM test order by cid, author LIMIT 10;

The serial number has come out, and an additional @ mid is added for grouping, with the focus on case when @ mid = author THEN @ row: = @ row + 1 ELSE @ row: = 1 END rownum, indicates that the group data is automatically traversed from 1 count.
SET @ row = 0; SET @ mid = ''; SELECT cid, author, case when @ mid = author THEN @ row: = @ row + 1 ELSE @ row: = 1 END rownum, @ mid: = author FROM test order by cid, author desc limit 20;

Now, add an inner JOIN to the table and then limit rownumber to get the target data.
SET @ row = 0;
SET @ mid = '';
SELECT a. *, B. rownum FROM test
Inner join (
SELECT cid, author, id, case when @ mid = author THEN @ row: = @ row + 1 ELSE @ row: = 1 END rownum, @ mid: = author MID
FROM test
Order by cid, author, id DESC
) B ON B. author = a. author AND B. cid = a. cid AND B. id = a. id WHERE B. rownum <3;


The execution result is as follows:

  1. Mysql> SET @ row = 0;
  2. Query OK, 0 ROWS affected (0.00 sec)


  3. Mysql> SET @ mid = \'\';
  4. Query OK, 0 ROWS affected (0.00 sec)


  5. Mysql> SELECT a. *, B. rownum FROM test
  6. -> Inner join (
  7. -> SELECT cid, author, id, case when @ mid = author THEN @ row: = @ row + 1 ELSE @ row: = 1 END rownum, @ mid: = author MID
  8. -> FROM test
  9. -> Order by cid, author, id DESC
  10. ->) B ON B. author = a. author AND B. cid = a. cid AND B. id = a. id WHERE B. rownum <3;
  11. + ----- + ------ + ---------------- + -------- +
  12. | Id | cid | author | rownum |
  13. + ----- + ------ + ---------------- + -------- +
  14. | 2 | 1 | test1 | 1 |
  15. | 1 | 1 | test1 | 2 |
  16. | 5 | 1 | test2 | 1 |
  17. | 4 | 1 | test2 | 2 |
  18. | 9 | 1 | test3 | 1 |
  19. | 8 | 1 | test3 | 2 |
  20. | 11 | 2 | test11 | 1 |
  21. | 10 | 2 | test11 | 2 |
  22. | 14 | 2 | test22 | 1 |
  23. | 13 | 2 | test22 | 2 |
  24. | 18 | 2 | test33 | 1 |
  25. | 17 | 2 | test33 | 2 |
  26. | 200 | 200 | 200test_nagios | 1 |
  27. + ----- + ------ + ---------------- + -------- +
  28. 13 rows in set (0.01 sec)


  29. Mysql>

Reference Article address:
Http://blog.csdn.net/mchdba/article/details/22163223
Http://blog.csdn.net/ylqmf/article/details/39005949










Sort the first two mysql groups

It can be written as select id, channel_id, time from table where group by channel_id order by time desc limit 2

Several records are retrieved after the mysql group is sorted,

# Mysql does not support ranking and statistical queries similar to rank () over in other complex databases
# It can only be implemented through the flexible subquery and logical computing methods, and can be considered for small data volumes

-- Rank ranking implementation
Select inline_rownum, aa, cc, amt, orderid FROM
(
Select
# Logic_cal only implements counter calculation. Each query is performed one by one to compare whether the current cc and @ last_cc are the same. If they are different, the current column value is assigned to @ last_cc and the counter is reset @ num: = 1, otherwise the counter is automatically added @ num: = @ num + 1
(Case when cc <> @ last_cc then concat (@ last_cc: = cc, @ num: = 1) else concat (@ last_cc, @ num: = @ num + 1) end) logic_cal
, @ Num as inline_rownum
, Aa, cc, amt, orderid
From tb_rank,
(Select @ last_cc: = '') t, # initialize @ last_cc to''. If the column to be checked (the column based on counter statistics) is int type, it is initialized to 0; varchar type is initialized''
(Select @ num: = 0) t2 # initialization @ num is 0
Order by cc, orderid asc # sorting method will affect @ num generation, because logic_cal is calculated row by row.
) T
Where inline_rownum <= floor (amt * 0.8) # limit the number of entries, take the constant value or other
Order by cc, orderid asc
;

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.