具有嵌套列表的MySQL查询

时间:2014-10-02 16:04:24

标签: mysql

我有一个电子商务表'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

但这不是有效的查询,我不确定我是否在正确的轨道上

2 个答案:

答案 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 |
  +-------+------------+-------+------+----------------------+----------------------+