日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

[MySQL] 分组排序取前N条记录以及生成自动数字序列,类似group by后 limit

發布時間:2023/12/9 数据库 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [MySQL] 分组排序取前N条记录以及生成自动数字序列,类似group by后 limit 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言:

????????同事的業務場景是,按照cid、author分組,再按照id倒敘,取出前2條記錄出來。

????????oracle里面可以通過row_number() OVER (PARTITION BY cid,author ORDER BY id DESC) 表示根據cid,author分組,在分組內部根據id排序,而此函數計算的值就表示每組內部排序后的順序編號(組內連續的唯一的),而mysql數據庫就沒有這樣的統計函數,需要自己寫復雜的sql來實現。


1,錄入測試數據

  • USE csdn;
  • DROP?TABLE?IF?EXISTS?test;
  • CREATE?TABLE?test?(
  • ??id INT?PRIMARY?KEY,
  • ??cid INT,
  • ??author?VARCHAR(30)
  • )?ENGINE=INNODB;


  • INSERT?INTO?test?VALUES?
  • (1,1,\'test1\'),
  • (2,1,\'test1\'),
  • (3,1,\'test2\'),
  • (4,1,\'test2\'),
  • (5,1,\'test2\'),
  • (6,1,\'test3\'),
  • (7,1,\'test3\'),
  • (8,1,\'test3\'),
  • (9,1,\'test3\'),
  • (10,2,\'test11\'),
  • (11,2,\'test11\'),
  • (12,2,\'test22\'),
  • (13,2,\'test22\'),
  • (14,2,\'test22\'),
  • (15,2,\'test33\'),
  • (16,2,\'test33\'),
  • (17,2,\'test33\'),
  • (18,2,\'test33\');
  • INSERT?INTO?test?VALUES?(200,200,\'200test_nagios\');

  • 2,原始的效率比較低下的子查詢實現方式
    SQL代碼如下:


  • SELECT?*?FROM?test a?
  • WHERE?
  • N>(
  • ????SELECT?COUNT(*)?
  • ????FROM?test b
  • ????WHERE?a.cid=b.cid?AND?a.`author`=b.`author`?AND?a.id<b.id
  • )ORDER?BY?cid,author,id?DESC;

  • 只要將N換成你要的數字比如2,就表示查詢出每個分組的前2條記錄,如下所示:

  • mysql>?SELECT?*?FROM?test a?
  • ????->?WHERE?
  • ????->?2>(
  • ????->?SELECT?COUNT(*)?
  • ????->?FROM?test b
  • ????->?WHERE?a.cid=b.cid?AND?a.`author`=b.`author`?AND?a.id<b.id
  • ????->?)ORDER?BY?cid,author,id?DESC;
  • +-----+------+----------------+
  • |?id?|?cid?|?author?|
  • +-----+------+----------------+
  • |?2?|?1?|?test1?|
  • |?1?|?1?|?test1?|
  • |?5?|?1?|?test2?|
  • |?4?|?1?|?test2?|
  • |?9?|?1?|?test3?|
  • |?8?|?1?|?test3?|
  • |?11?|?2?|?test11?|
  • |?10?|?2?|?test11?|
  • |?14?|?2?|?test22?|
  • |?13?|?2?|?test22?|
  • |?18?|?2?|?test33?|
  • |?17?|?2?|?test33?|
  • |?200?|?200?|?200test_nagios?|
  • +-----+------+----------------+
  • 13?ROWS?IN?SET?(0.00 sec)


  • mysql>


  • 3,使用動態sql來實現
    先構造序列號碼,引入一個@row來做rownumber
    SET @row=0;SET @mid='';SELECT cid, author, @row:=@row+1 rownum FROM test ORDER BY ?cid, author LIMIT 10; ??

    序列號碼已經出來了,再加一個@mid來進行分組,重點在于CASE WHEN @mid = author THEN @row:=@row+1 ELSE @row:=1 END rownum,表示分組的時候會自動從1計數指導這個分組數據遍歷結束。
    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; ?

    好了,再外面加一層inner JOIN 再對 rownumber 做限制 就可以拿到目標數據了。
    SET @row=0;
    SET @mid='';
    SELECT a.*,b.rownum FROM test a?
    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; ?


    執行結果如下所示:

  • mysql>?SET?@row=0;
  • QUERY OK,?0?ROWS?affected?(0.00 sec)


  • mysql>?SET?@mid=\'\';
  • QUERY OK,?0?ROWS?affected?(0.00 sec)


  • mysql>?SELECT?a.*,b.rownum?FROM?test a?
  • ????->?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;?
  • +-----+------+----------------+--------+
  • |?id?|?cid?|?author?|?rownum?|
  • +-----+------+----------------+--------+
  • |?2?|?1?|?test1?|?1?|
  • |?1?|?1?|?test1?|?2?|
  • |?5?|?1?|?test2?|?1?|
  • |?4?|?1?|?test2?|?2?|
  • |?9?|?1?|?test3?|?1?|
  • |?8?|?1?|?test3?|?2?|
  • |?11?|?2?|?test11?|?1?|
  • |?10?|?2?|?test11?|?2?|
  • |?14?|?2?|?test22?|?1?|
  • |?13?|?2?|?test22?|?2?|
  • |?18?|?2?|?test33?|?1?|
  • |?17?|?2?|?test33?|?2?|
  • |?200?|?200?|?200test_nagios?|?1?|
  • +-----+------+----------------+--------+
  • 13?ROWS?IN?SET?(0.01 sec)


  • mysql>
  • 總結

    以上是生活随笔為你收集整理的[MySQL] 分组排序取前N条记录以及生成自动数字序列,类似group by后 limit的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。