【问题标题】:Select 2 products from each category in MySQL从 MySQL 中的每个类别中选择 2 个产品
【发布时间】:2011-04-12 10:14:13
【问题描述】:

与MYSQL - select first 4 records for each category in a table 非常相似,但没有公认的答案,而且那里的一个答案没有多大意义,所以我再次询问。

我有一个包含 3 列的 PRODUCTS 表:ID、NAME 和 CATEGORY 我现在想知道的是,是否可以为每个不同的类别选择 2 个产品,而无需在 PHP 循环中进行查询。

所选产品的顺序无关紧要,它们也可能是随机的。但重要的是,我每个类别最多只能有 2 个产品。

所以一个好的结果集应该是

ID  ; NAME   ; CATEGORY
:::::::::::::::::::::::
152 ; APPLE  ; FRUIT
185 ; ORANGE ; FRUIT
145 ; BEEF   ; MEAT
141 ; PORK   ; MEAT
410 ; PEPSI  ; DRINKS
585 ; CARROT ; VEGETABLES
585 ; TOMATO ; VEGETABLES

【问题讨论】:

  • 你的结果应该如何?把它放在你的代码中以便更好地理解

标签: php mysql


【解决方案1】:

这些方面的东西会起作用:

SELECT id, name, category 
FROM (
  SELECT *, 
         IF( @prev <> category, 
             @rownum := 1, 
             @rownum := @rownum+1 
         ) AS rank, 
         @prev := category, 
         @rownum  
  FROM (
    SELECT * FROM products 
    ORDER BY category, rand()
  ) random_prodcts
) products_ranked 
WHERE rank <= 2;

它在类别中随机排序,然后将它们拉出来跟踪每个类别的数量。

但不确定它的扩展效果如何。

编辑:尝试了几千条记录,似乎还可以。

【讨论】:

  • 这很好用。只需确保在运行查询之前设置了变量。否则它将无法正常工作。 SET @prev=0,@rownum=0;
  • MariaDB 工作正常,但 MySQL 不工作
【解决方案2】:

这应该可以满足您的需求。

SET @I=0; 
SET @C='';
SELECT ID, Name, Category FROM (
    SELECT B.*, 
    IF(@C != B.Category, @I:=1, @I:=@I+1) AS RowNum,
    @C:=B.Category
    FROM (
        SELECT ID, Name, Category FROM Products GROUP BY Name, Category ORDER BY Category
    ) AS B HAVING RowNum <= 2
) AS A

【讨论】:

  • 谢谢,这似乎可行,但我似乎无法理解 RowNum var ...当我选择它以及 ID、名称和类别列时,它有时也包含 3 而HAVING 子句声明它不应高于 2?
  • 这真的很奇怪 - 我刚刚尝试过这个,并注意到它适用于
  • @Simon143:是的,您的解决方案实际上给了我正确的 rowNumbers ...谢谢!
【解决方案3】:

完整的 SQL:

SELECT t.id, t.name, t.category
FROM the_table AS t
, (SELECT MIN(id) AS id_min FROM the_table GROUP BY category) AS t1
, (SELECT MAX(id) AS id_max FROM the_table GROUP BY category) AS t2
WHERE (t.id=t1.id_min) OR  (t.id=t2.id_max)

查询选择每个类别的最小值和最大值并返回它们(如果相同,则只返回一个)。

您说“选择的产品的顺序不重要,它们还不如随机”,所以这种方法应该可以。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-19
    • 1970-01-01
    • 1970-01-01
    • 2018-08-26
    • 2015-03-02
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    相关资源
    最近更新 更多