公司前段時間碰到如下的報表需求:
查詢某個用戶購買金額最大的前三條記錄,如下:
customer price
A 1000
A 888
A 333
B 12222
B 12000
C 3000
C 2000
然后需要通過SQL將其變成四個字段
Customer price1 price2 price3
A 1000 888 333
B 12222 12000
C 3000 2000
這個問題牽涉到兩個問題,一個取前N位的SQL,另一個將行記錄怎么變成列字段。
第一個問題好解決:
1 select a.customer,a.price,count(b.price) as rn
2 from pt a join pt b on a.customer=b.customer and a.price<=b.price
3 groupby a.customer,a.price;
結果:
+----------+-------+----+
| customer | price | rn |
+----------+-------+----+
| A | 333 | 3 |
| A | 888 | 2 |
| A | 1000 | 1 |
| B | 12000 | 2 |
| B | 12222 | 1 |
| C | 2000 | 2 |
| C | 3000 | 1 |
+----------+-------+----+
然后就是將行記錄變成列字段,這里采用if判斷關鍵字,對上面的查詢結果進行如下操作:
1 select
2
3 customer, (if(rn=1,price,'')) as price1, (if(rn=2,price,'')) as price2,
4
5 (if(rn=3,price,'')) as price3 from a;
執行結果如下所示:
+----------+--------+--------+--------+
| customer | price1 | price2 | price3 |
+----------+--------+--------+--------+
| A | 143.20 | | |
| A | | 99.99 | |
| A | | | 49.99 |
| B | 63.92 | | |
| B | | 33.99 | |
| C | 99.99 | | |
| C | | 24.10 | |
+----------+--------+--------+--------+
針對這個執行結果執行如下的sql既可以得到我們期望的結果了:
select customer,
max(if(rn=1,price,'')) as price1,
max(if(rn=2,price,'')) as price2,
max(if(rn=3,price,'')) as price3
from (
select a.customer,a.price,count(b.price) as rn
from pt a join pt b on a.customer=b.customer and a.price<=b.price
groupby a.customer,a.price )k
groupby customer;
+----------+--------+--------+--------+
| customer | price1 | price2 | price3 |
+----------+--------+--------+--------+
| A |1000 |888 |333 |
| B |12222 |12000 | |
| C |3000 |2000 | |
+----------+--------+--------+--------+
上面的記錄中,價格沒有重復的情況,如果有重復的,那么上面的結果方案是不行的,下面是一個辦法:
1 createtable pt(customer varchar(19),price int);
2 insert pt select
3 'A',1000 union all select
4 'A',1000 union all select
5 'A', 888 union all select
6 'A',333 union all select
7 'B', 12222 union all select
8 'B', 12000 union all select
9 'C', 3000 union all select
10 'C', 2000;
11
12 set@n=0;
13 createtable kos select*,@n:=@n+1as id from pt; --建立個輔助表
14
15 select customer,
16 max(if(rn=1,price,'')) as price1,
17 max(if(rn=2,price,'')) as price2,
18 max(if(rn=3,price,'')) as price3,
19 from (
20 select a.customer,a.price,a.id,count(b.id) as rn
21 from kos a join kos b on a.customer=b.customer and a.id>=b.id
22 groupby a.customer,a.price,a.id )k
23 groupby customer;
執行結果如下:
+----------+--------+--------+--------+--------+
| customer | price1 | price2 | price3 | price4 |
+----------+--------+------+--------+------+
| A |1000 |1000 |888 |333 |
| B |12222 |12000 | | |
| C |3000 |2000 | | |
+----------+--------+--------+--------+------+