我有一个电子商务表'orders',该表有一个'state'记录和一个'fruit'记录。我正在尝试(并且失败)创建一个查询,该查询将返回每个州的结果和前3个最受欢迎的水果,按顺序显示。
所以'orders'表看起来像这样:
id State Fruit
----------------
1 CA grape
2 FL orange
3 CA grape
4 FL grapefruit
5 CA orange
6 CA grape
7 FL orange
8 CA peach
9 CA orange
10 FL orange
11 FL grapefruit
12 FL peach
etc etc etc
此表上的查询结果为:
the_state the_fruits
------------------------
CA grape, orange, peach
FL orange, grapefruit, peach
我试过了:
SELECT state as the_state,
(select count(id) as count, fruit from orders where state = the_state order by count(id) limit 3 ) as the_fruits
FROM orders
group by fruit
order by count(id) DESC
但这不是有效的查询,我不确定我是否在正确的轨道上
答案 0 :(得分:1)
限制MySQL中分组数据的结果非常困难。各种线程上有许多解决方案,但它可能在很大程度上取决于您拥有的数据类型和数量。
以下可能是最简单的解决方案。
mysql> INSERT INTO orders VALUES
-> ('1', 'CA', 'grape'),
-> ('2', 'FL', 'orange'),
-> ('3', 'CA', 'grape'),
-> ('4', 'FL', 'grapefruit'),
-> ('5', 'CA', 'orange'),
-> ('6', 'CA', 'grape'),
-> ('7', 'FL', 'orange'),
-> ('8', 'CA', 'peach'),
-> ('9', 'CA', 'orange'),
-> ('10', 'FL', 'orange'),
-> ('11', 'FL', 'grapefruit'),
-> ('12', 'FL', 'peach'),
-> ('13', 'CA', 'apple'),
-> ('14', 'FL', 'apple');
Query OK, 14 rows affected (0.03 sec)
Records: 14 Duplicates: 0 Warnings: 0
mysql> select state, fruit, count(fruit) cf from orders group by state, fruit order by state, cf desc;
+-------+------------+----+
| state | fruit | cf |
+-------+------------+----+
| CA | grape | 3 |
| CA | orange | 2 |
| CA | peach | 1 |
| CA | apple | 1 |
| FL | orange | 3 |
| FL | grapefruit | 2 |
| FL | peach | 1 |
| FL | apple | 1 |
+-------+------------+----+
8 rows in set (0.00 sec)
SELECT state
, SUBSTRING_INDEX(GROUP_CONCAT(fruit ORDER BY cf DESC, fruit),',',3) top3
FROM
( SELECT state
, fruit
, COUNT(fruit) cf
FROM orders
GROUP
BY state
, fruit
) t1
GROUP
BY state;
+-------+-------------------------+
| state | top3 |
+-------+-------------------------+
| CA | grape,orange,peach |
| FL | orange,grapefruit,apple |
+-------+-------------------------+
2 rows in set (0.00 sec)
答案 1 :(得分:0)
正如doog abides指出的那样,我以前的解决方案处理得很差。这是一个替代方案,使用我之前提到的变量。它的速度也非常快......
DROP TABLE IF EXISTS orders;
CREATE TABLE orders
( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, state CHAR(2)
, fruit VARCHAR(20) NOT NULL
);
INSERT INTO orders VALUES
(1 ,'CA','grape'),
(2 ,'FL','orange'),
(3 ,'CA','grape'),
(4 ,'FL','grapefruit'),
(5 ,'CA','orange'),
(6 ,'CA','grape'),
(7 ,'FL','orange'),
(8 ,'CA','peach'),
(9 ,'CA','orange'),
(10 ,'FL','orange'),
(11 ,'FL','grapefruit'),
(12 ,'FL','peach'),
(13 ,'FL','banana');
SELECT state
, fruit
, total
, IF(@prev_state = state, IF(@prev_total=total,@rank,@rank:=@rank+1),@rank:=1) rank
, @prev_state := state
, @prev_total := total
FROM
( SELECT state
, fruit
, COUNT(*) total
FROM orders
GROUP
BY state
, fruit
) x
, ( SELECT @prev_state := null, @prev_total:=null, @rank := 0) vars
ORDER
BY state,total DESC;
+-------+------------+-------+------+----------------------+----------------------+
| state | fruit | total | rank | @prev_state := state | @prev_total := total |
+-------+------------+-------+------+----------------------+----------------------+
| CA | grape | 3 | 1 | CA | 3 |
| CA | orange | 2 | 2 | CA | 2 |
| CA | peach | 1 | 3 | CA | 1 |
| FL | orange | 3 | 1 | FL | 3 |
| FL | grapefruit | 2 | 2 | FL | 2 |
| FL | banana | 1 | 3 | FL | 1 |
| FL | peach | 1 | 3 | FL | 1 |
+-------+------------+-------+------+----------------------+----------------------+