【问题标题】:Selecting the latest entry of multiple unique category ID's选择多个唯一类别 ID 的最新条目
【发布时间】:2019-01-17 14:08:05
【问题描述】:
Table Name: entries
ID (int)
rootID (int) 
categoryID (int)
editDate (dateTime [ default null ])
createdDate (dateTime [ default NOW() ]) 

  +--+--------+----------+---------------------+---------------------+
  |ID| rootID |categoryID|       editDate      |     createdDate     |
  +--+--------+----------+---------------------+---------------------+
  | 1|    1   |     1    | 2018-05-02 18:59:01 | 2018-04-01 18:52:37 | 
  | 2|    1   |     1    |        null         | 2018-05-02 18:59:01 |
  | 3|    3   |     1    | 2018-06-10 19:32:01 | 2018-06-10 19:12:01 |
  | 4|    3   |     1    | 2018-07-11 18:52:01 | 2018-06-10 19:32:01 |
  | 5|    3   |     1    |        null         | 2018-07-11 18:52:01 |
  | 6|    6   |     1    | 2018-10-09 12:38:01 | 2018-10-09 12:27:01 |
  | 7|    6   |     1    |        null         | 2018-10-09 12:38:01 |
  | 8|    8   |     2    | 2018-11-09 08:12:11 | 2018-12-09 10:12:01 |
  | 9|    8   |     2    |        null         | 2018-11-09 08:12:11 |
  +--+--------+----------+---------------------+---------------------+

您好,我正在尝试从具有此结构的表中选择信息。我需要从所有 rootID 中返回类别 1 中的所有行,但仅在 editDate 为 null 的情况下以及每个 rootID 中的 min(createdDate) 处返回。

我希望得到第 2、5 和 7 行的结果。但是,如果要将 ID[4] 的 editDate 值替换为 NULL,那么对于 rootID 3,必须返回 ID 4 而不是 5。

我一直在寻找类似的帖子,我找到的最接近的是这个: SQL MIN Function with where clause

我觉得我很接近我在那里找到的一个例子,但他们使用了两个表,我只能使用这个。这是我现在正在尝试的:

SELECT * FROM entries e WHERE e.categoryID=1 AND e.editDate is NULL AND e.createdDate in(SELECT min(createdDate) FROM entries)

但是,这仅从第一个 rootID 的最早创建日期返回一个条目。我无法理解查询,但我开始了解它是如何仅引用一个条目的。

我正在寻找的是从 categoryID=1,找到每个不同 rootID 的 ID,其中最早 createdDate 的行具有 NULL 编辑日期。如何更改它以从每个根返回一个?谢谢大家的时间。我将继续发布今晚尝试的 SQL。

【问题讨论】:

    标签: mysql sql select min


    【解决方案1】:

    您的示例的问题在于,它仅选择 createdDate 与整个表中的一个最小 cre​​atedDate 匹配的行。这就是 SELECT min(createdDate) FROM 条目的作用,只返回一个 createdDate。

    我认为您需要做的是找到一种方法来为每个给定的 rootId 选择最小 cre​​atedDate。我会尝试这样的事情:

    SELECT *
      FROM entries A
     WHERE A.categoryId = 1
       AND A.editDate IS NULL
       AND A.createdDate = (SELECT MIN(B.createdDate)
                              FROM entries B
                             WHERE A.rootId     = B.rootId
                               AND B.categoryId = 1
                               AND B.editDate  IS NULL);
    

    这样,您从表中进行选择,其中 categoryId 为 1,editDate 为 null,createdDate 与 categoryId = 1、editDate null 和 rootId 匹配的所有行的最小 cre​​atedDate 匹配外部查询正在查看的行。

    【讨论】:

    • 太棒了,谢谢香农,我现在就试试看。
    • 香农!感谢您分享它,它完美地工作,并感谢其他所有对此提出任何想法的人。
    • 不客气!我很高兴能够提供帮助!
    【解决方案2】:

    我想你想要这个:

    SELECT *
    FROM entries A
    WHERE Id IN (
        SELECT Id
        FROM entries B
        WHERE A.rootId = B.rootId
        AND A.categoryId = B.categoryId
        AND B.editDate IS NULL
        AND categoryId = 1
        AND A.createdDate = B.createdDate
    )
    GROUP BY rootId, categoryId
    HAVING createdDate = MIN(createdDate)
    

    【讨论】:

    • 这听起来像是我需要的,但我遇到了一些麻烦。我在 TOP 1 中的“1”的第 4 行收到错误。这是否意味着 TOP 1 在我的 MySQL 版本中不可用?我相信它是 5.6.2
    • 注意@Keith Harris
    • 哦...您使用的是 MySQL,而不是 SQL Server。让我编辑我的答案。
    • 非常感谢。但是如果我得到以下错误,我只是不走运吗?:(这个版本的 MySQL 还不支持 'LIMIT & IN/ALL/ANY/SOME subquery')
    • MySQL 语法比我想象的要难......我编辑了我的答案。我认为这一次会奏效。
    【解决方案3】:

    这适用于 SQL Server 和 MySQL

    SELECT e.*
     FROM 
     (
        SELECT rootID, MIN(CASE WHEN editDate IS NULL THEN ID ELSE NULL END) AS editDateId, MIN(createdDate) AS minCreatedDate
        FROM entries
        WHERE categoryID = 1
        GROUP BY rootID
      ) t
      JOIN  entries e
      ON    e.ID = (case when t.editDateId IS NOT NULL THEN editDateId END) OR
            (t.editDateId IS NULL AND createdDate = t.minCreatedDate)
    

    【讨论】:

      猜你喜欢
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 2021-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-29
      相关资源
      最近更新 更多