【问题标题】:Select number of rows from each category从每个类别中选择行数
【发布时间】:2018-03-27 06:08:28
【问题描述】:

我有消息表: 消息:

Id, Content, Category, createdAt 

1, test1, cat1, 2018-03-26 18:22:39  
2, test2, cat1, 2018-03-26 18:22:46 
3, test3, cat2, 2018-03-26 18:22:52 
4, test4, cat2, 2018-03-26 18:23:11  
5, test5, cat2, 2018-03-26 18:23:13
6, test6, cat1, 2018-03-26 18:23:17  

从这些数据中,我想选择每个类别的 2 行,即 Cat1 和 Cat2,每行 2 行。

那么检索这些数据的 SQL 查询是什么?这是示例数据,就像这样,我有数千行和 20 到 25 个不同的类别。所以我想从每个类别中检索相同数量的行。此外,这些行应根据 createdAt 列按升序排列。

预期输出(假设 createdAt 是最后一行):

Id, Content, Category, createdAt 

6, test6, cat1, 2018-03-26 18:23:17  
2, test2, cat1, 2018-03-26 18:22:46  
5, test5, cat2, 2018-03-26 18:23:13
4, test4, cat2, 2018-03-26 18:23:11 

【问题讨论】:

  • 指定预期结果。并向我们​​展示您当前的查询尝试。
  • 使用“按类别分组”
  • 我在问题中添加了预期的输出。按类别分组,每个类别只返回单行。所以在这种情况下可能需要嵌套查询
  • 您的表头有 4 列,但表数据只有 3 列。 createdAt 似乎不见了。那一栏重要吗?
  • 好的,我也会添加 createdAt 的值

标签: mysql sql


【解决方案1】:

使用动态顶部 你可以用任何数字代替 N

SELECT Id,Content,Category,createdAt
  FROM (SELECT t.*,
               CASE 
                 WHEN @category != t.category THEN @rownum := 1 
                 ELSE @rownum := @rownum + 1 
               END AS rank,
               @category := t.category AS var_category
          FROM Table1 t
          JOIN (SELECT @rownum := NULL, @category := '') r
      ORDER BY t.Category,t.createdAt DESC) x
 WHERE x.rank <= 'N'

你可以用任何数字代替 N

输出

ID  Content Category    createdAt
6   test6   cat1    2018-03-26T18:23:17Z
2   test2   cat1    2018-03-26T18:22:46Z
5   test5   cat2    2018-03-26T18:23:13Z
4   test4   cat2    2018-03-26T18:23:11Z 

现场演示

http://sqlfiddle.com/#!9/00ca02/20

【讨论】:

  • 再次从每个类别返回单行。我需要每个类别中的 2 行。
  • 现在检查我编辑了我的答案
  • 它适用于 2 行。但实际上我希望每个类别有 200 行,那么是否可以概括此查询以指定每个类别的 n 条记录?
  • 现在检查我也添加了概括答案
【解决方案2】:

由于没有 row_Number() 函数是 MySql 它变得有点棘手。

select 
  a.Id, a.Content, a.Category, a.createdAt
from Table1 a
JOIN Table1 b ON a.Category = b.Category AND a.createdAt <= b.createdAt
GROUP BY a.Category, a.createdAt
having count(*) <= 2
order by Category, CreatedAt desc

【讨论】:

    【解决方案3】:

    我猜这个排名就是你要找的

    SELECT
      (
        CASE category
        WHEN @curCat
          THEN @curRow := @curRow + 1
        ELSE @curRow := 1 AND @curCat := category END
      ) + 1 AS rank,
      category,
      id,
      content
    FROM tab1,
      (SELECT
         @curRow := 0,
         @curType := '') r
    ORDER BY category
             AND rank <= 2;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-13
      • 1970-01-01
      • 2011-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-24
      相关资源
      最近更新 更多