MySQL top-N排名,然后将同一组的其余部分求和

Che*_*How 1 mysql aggregate sum top-n

我大部分时间都在研究这个主题,但是对于使用group()和使用sum()进行聚合的MySQL表的排名(前3名),我没有一个有效而完美的答案。

数据如下:

TS         | Name     | Count
=============================
1552286160 | Apple    | 7
1552286160 | Orange   | 8
1552286160 | Grape    | 8
1552286160 | Pear     | 9
1552286160 | Kiwi     | 10
...
1552286100 | Apple    | 10
1552286100 | Orange   | 12
1552286100 | Grape    | 14
1552286100 | Pear     | 16
1552286100 | Kiwi     | 9
...
1552286040 | Apple    | 4
1552286040 | Orange   | 2
1552286040 | Grape    | 3
1552286040 | Pear     | 7
1552286040 | Kiwi     | 9
...
Run Code Online (Sandbox Code Playgroud)

有了这个数据集,我想按每个TS组形成前3名,并用该组其余部分的sum(Count)构成1行,如下所示:

TS         | Name     | Count
=============================
1552286160 | Kiwi     | 10
1552286160 | Pear     | 9
1552286160 | Grape    | 8
1552286160 | Other    | 8 + 7
...
1552286100 | Pear     | 16
1552286100 | Grape    | 14
1552286100 | Orange   | 12
1552286100 | Other    | 10 + 9
...
1552286040 | Kiwi     | 9
1552286040 | Pear     | 7
1552286040 | Apple    | 4
1552286040 | Other    | 3 + 2
...
Run Code Online (Sandbox Code Playgroud)

实际上,最接近的提示是通过http://www.silota.com/docs/recipes/sql-top-n-aggregate-rest-other.html提供的但是,该解决方案仅适用于单个组。

我准备的SQL Fiddle位于此处:http : //sqlfiddle.com/#!9/3cedd0/10

赞赏是否有任何解决方案。

Str*_*rry 5

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(ts INT NOT NULL
,name VARCHAR(12) NOT NULL
,count INT NOT NULL
,PRIMARY KEY(ts,name)
);

INSERT INTO my_table VALUES
(1552286160,'Apple' , 7),
(1552286160,'Orange', 8),
(1552286160,'Grape' , 8),
(1552286160,'Pear'  , 9),
(1552286160,'Kiwi'  ,10),
(1552286100,'Apple' ,10),
(1552286100,'Orange',12),
(1552286100,'Grape' ,14),
(1552286100,'Pear'  ,16),
(1552286100,'Kiwi'  , 9),
(1552286040,'Apple' , 4),
(1552286040,'Orange', 2),
(1552286040,'Grape' , 3),
(1552286040,'Pear'  , 7),
(1552286040,'Kiwi'  , 9);

SELECT ts
     , CASE WHEN i>3 THEN 'other' ELSE name END name
     , SUM(count) count
  FROM 
     ( SELECT x.*
            , CASE WHEN @prev=ts THEN @i:=@i+1 ELSE @i:=1 END i
            , @prev:=ts 
         FROM my_table x
            , (SELECT @prev:=null,@i:=0) vars 
        ORDER 
           BY ts
            , count DESC
            , name
     ) a
 GROUP
    BY ts
     , CASE WHEN i>3 THEN 'other' ELSE name END;

+------------+--------+-------+
| ts         | name   | count |
+------------+--------+-------+
| 1552286040 | Apple  |     4 |
| 1552286040 | Kiwi   |     9 |
| 1552286040 | other  |     5 |
| 1552286040 | Pear   |     7 |
| 1552286100 | Grape  |    14 |
| 1552286100 | Orange |    12 |
| 1552286100 | other  |    19 |
| 1552286100 | Pear   |    16 |
| 1552286160 | Grape  |     8 |
| 1552286160 | Kiwi   |    10 |
| 1552286160 | other  |    15 |
| 1552286160 | Pear   |     9 |
+------------+--------+-------+
Run Code Online (Sandbox Code Playgroud)