SQL SELECT MAX() 返回多条记录

Posted

技术标签:

【中文标题】SQL SELECT MAX() 返回多条记录【英文标题】:SQL SELECT MAX() is returning multiple records 【发布时间】:2017-06-02 16:21:38 【问题描述】:

我正在尝试编写一个 SQL 查询,以带回具有 MAX ID2 和 MAX DATETIME 的记录

在我目前的结果中,

存在具有相同 nmae 和 special_number 的记录。它们仅在 ID2 和 Date_Time 上有所不同。 special_number 应该是唯一的并且没有重复。如果有重复的special_number,则选择ID2和date_time最大的记录

对于重复项(有很多),我只需要选择具有 MAx ID2 和 DATE_TIME 的记录。 比如ADDEN CROSS,我只需要带回ID2 = 333和2017-05-05的ADDEN CROSS即可。

我试过 MAX 但没用

SELECT DISTINCT ID, NAME, MAX(ID2), SPECIAL_NUMBER and DATE_TIME
FROm TABLE1
WHERE DATE_TIME BETWEEN @START_DATE and @END_DATE
GROUP BY ID, ID2, SPECIAL_NUMBER, DATE_TIME

感谢任何帮助。谢谢

我目前的结果

ID      NAME        ID2     SPECIAL_NUMBER  DATE_TIME   
123     JOE SMITH   456     D123            2017-06-05
123     JOE SMITH   455     D123            2017-06-04
124     JIM DONE    111     E111            2017-06-02
122     ME TOO      222     G111            2017-06-01
146     ADDEN CROSS 333     R555            2017-05-05
146     ADDEN CROSS 332     R555            2017-05-04
146     ADDEN CROSS 331     R555            2017-05-02

我的预期结果

ID      NAME        ID2     SPECIAL_NUMBER  DATE_TIME   
123     JOE SMITH   456     D123            2017-06-05
124     JIM DONE    111     E111            2017-06-02
122     ME TOO      222     G111            2017-06-01
146     ADDEN CROSS 333     R555            2017-05-05

【问题讨论】:

【参考方案1】:

你可以使用 top n 与下面的关系

Select top (1) with ties * from yourtable
    order by row_number() over(partition by name order by Id2 desc)

【讨论】:

从来没想过用WITH TIES代替子查询,这样更优雅! 但是这样的子查询性能更好,因为 top 1 with ties 包括一个排序运算符...检查我在这个问题中的答案:***.com/questions/44310873/… 是的,我自己在相对简单的表上比较了执行计划。子查询似乎更丑更有效。【参考方案2】:

嗯,你的结果是独一无二的,我怀疑你想根据日期获得最新的 ID2。

在这种情况下,您可以使用ROW_NUMBER()

SELECT *
FROM (  SELECT ROW_NUMBER() OVER (PARTITION BY ID, NAME, SPECIAL_NUMBER, DATE_TIME ORDER BY ID2 DESC) AS RN
          , ID
          , NAME
          , ID2
          , SPECIAL_NUMBER
          , DATE_TIME
        FROM TABLE1
        WHERE DATE_TIME BETWEEN @START_DATE and @END_DATE) AS T
WHERE T.RN = 1;

【讨论】:

【参考方案3】:

您获得多条记录的原因是GROUP BY 子句。

考虑顶部的两行:

ID      NAME        ID2     SPECIAL_NUMBER  DATE_TIME   
123     JOE SMITH   456     D123            2017-06-05
123     JOE SMITH   455     D123            2017-06-04

由于IDID2SPECIAL_NUMBERDATE_TIME都是GROUP BY中的列,因此SQL无法将这两条记录合并为符合您期望的一条:

ID      NAME        ID2     SPECIAL_NUMBER  DATE_TIME   
123     JOE SMITH   456     D123            2017-06-05

ID2 的值可以是 455 或 456; SQL 无法选择其中一个。同样,DATE_TIME 可以是2017-06-052017-06-04,如果没有您明确指示选择MAX,DB 无法决定应该选择哪一个。

我试过MAX,但没用

你已经很接近了——删除DISTINCT,并从列表中删除ID2DATE_TIME

SELECT ID, NAME, MAX(ID2), SPECIAL_NUMBER, MAX(DATE_TIME)
FROM TABLE1
WHERE DATE_TIME BETWEEN @START_DATE and @END_DATE
GROUP BY ID, SPECIAL_NUMBER

【讨论】:

如果ID2 不是最新DATE_TIME 最高的记录,这可能会给出不正确的数据,也许它在他的数据中,但有机会。 :) @EvaldasBuinauskas OP 的声明“我只需要选择具有 MAX ID2DATE_TIME 的记录”意味着两者在同一记录上变为 MAX。否则,选择将是模棱两可的。【参考方案4】:

WITH e AS ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY ID, Name, SPECIAL_NUMBER ORDER BY ID2 DESC ) AS R FROM TABLE1 ) SELECT ID, NAME, ID2, SPECIAL_NUMBER, DATE_TIME FROM e WHERE DATE_TIME BETWEEN @START_DATE and @END_DATE

【讨论】:

以上是关于SQL SELECT MAX() 返回多条记录的主要内容,如果未能解决你的问题,请参考以下文章

SQL 查询将多条记录中的值组合到单个列中

mybatis select返回多条记录即返回类型为list时

mybatis select返回多条记录即返回类型为list时

SQL 查询多条符合条件的记录

SQL 查询:如果满足搜索条件,则应返回单条记录,否则返回多条记录

sql server返回插入记录的ID(多条记录)