【问题标题】:How to get the latest 2 items per category in one select (with mysql)如何在一次选择中获取每个类别的最新 2 个项目(使用 mysql)
【发布时间】:2010-11-08 16:26:02
【问题描述】:

我的数据如下所示:

id|类别|插入日期|标题.... -------------------------------- 1|1|123|测试 1 2|1|124|测试 2 3|1|125|测试 3 4|2|102|测试 4 5|2|103|测试 5 6|2|104|测试 6

我尝试完成的是获取每个类别的最新 2 个条目(按照 insertdate DESC 的顺序),所以结果应该是:

身份证|.... ---- 3|.... 2|.... 6|.... 5|....

使用group by 获取最新的很容易,但是如何在不启动多个查询的情况下获取最新的 2?

感谢您的帮助;-)
S.

【问题讨论】:

    标签: sql mysql


    【解决方案1】:
    SELECT * 
    FROM category AS c1
    WHERE (
        SELECT COUNT(c2.id)
        FROM category AS c2
        WHERE c2.id = c1.id AND c2.insertdate > c1.insertdate
    ) < 2
    

    【讨论】:

      【解决方案2】:

      另一种方法是使用 group_concat 获取有序列表。如果你有很多数据,这真的没有任何用处。

      select group_concat(id order by insertdate desc separator ','), category from tablename group by category
      

      或使用子选择(在 mysql 上)

      select category,
          (select id from test as test1 where test1.category = test.category order by insertdate desc limit 0,1) as recent1,
          (select id from test as test1 where test1.category = test.category order by insertdate desc limit 1,1) as recent2
      from test
      group by category;
      

      我知道第二个选项在技术上不是一个选择,因为有子查询,但这是我能看到的唯一方法。

      【讨论】:

        【解决方案3】:

        这是 SQL 中的一个棘手问题,最好通过将您定向到涵盖该问题的优秀深入文章来回答:How to select the first/least/max row per group in SQL。它涵盖了执行此操作的特定于 MySQL 的方法,以及通用方法。

        【讨论】:

        • 优秀的资源!一个更详尽的答案,其中包含更清晰的细节。
        【解决方案4】:

        你来了,伙计!

        SET @counter = 0;
        SET @category = '';
        
        SELECT
            *
        FROM
        (
            SELECT
                @counter := IF(data.category = @category, @counter+1, 0) AS counter,
                @category := data.category,
                data.*
            FROM
            (
                SELECT
                    *
                FROM test
                ORDER BY category, date DESC
            ) data
        ) data
        HAVING counter < 2
        

        【讨论】:

        • 这应该是一个 WHERE 计数器
        • 我试图在第二个子选择中使用 HAVING,但计数器“此时尚未设置”或“优化器在 @counter 之前执行了”......因此当然会有 WHERE也可以在外面做这项工作。
        【解决方案5】:

        您无法在一个 SELECT 语句中执行此类查询,但您可以将其包装在一个存储过程中,该存储过程通过将子查询的结果添加到每个类别的临时表中来返回一个数据集,然后返回临时表的内容。

        伪代码:

        Create a temp table
        For each distinct category,
          Add the last two records to the temp table
        Return the temp table
        

        您最终会得到您想要的一组数据,并且从您的应用程序的角度来看,只进行了一次查询。

        【讨论】:

          猜你喜欢
          • 2010-11-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-07-13
          • 1970-01-01
          相关资源
          最近更新 更多