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
由于ID
、ID2
、SPECIAL_NUMBER
和DATE_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-05
或2017-06-04
,如果没有您明确指示选择MAX
,DB 无法决定应该选择哪一个。
我试过
MAX
,但没用
你已经很接近了——删除DISTINCT
,并从列表中删除ID2
和DATE_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 ID2
和 DATE_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() 返回多条记录的主要内容,如果未能解决你的问题,请参考以下文章
mybatis select返回多条记录即返回类型为list时
mybatis select返回多条记录即返回类型为list时