MySQL top-N 排名和同组其余总和
MySQL top-N ranking and sum the rest of same group
我大部分时间都在研究这个主题,但是我无法得到关于排名(前 3)的有效和完美的答案 MySQL table 组和聚合使用sum() 到其余部分。
数据如下:
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
...
使用此数据集,我想按每个 TS 组形成前 3 名,并在 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
...
最接近的提示实际上是通过 http://www.silota.com/docs/recipes/sql-top-n-aggregate-rest-other.html 提供的,但是,该解决方案仅适用于单个组。
我准备的SQLFiddle位于:http://sqlfiddle.com/#!9/3cedd0/10
如有任何解决方案,不胜感激。
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 |
+------------+--------+-------+
我大部分时间都在研究这个主题,但是我无法得到关于排名(前 3)的有效和完美的答案 MySQL table 组和聚合使用sum() 到其余部分。
数据如下:
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
...
使用此数据集,我想按每个 TS 组形成前 3 名,并在 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
...
最接近的提示实际上是通过 http://www.silota.com/docs/recipes/sql-top-n-aggregate-rest-other.html 提供的,但是,该解决方案仅适用于单个组。
我准备的SQLFiddle位于:http://sqlfiddle.com/#!9/3cedd0/10
如有任何解决方案,不胜感激。
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 |
+------------+--------+-------+