SQL Server:仅选择具有 MAX(DATE) 的行
Posted
技术标签:
【中文标题】SQL Server:仅选择具有 MAX(DATE) 的行【英文标题】:SQL Server: SELECT only the rows with MAX(DATE) 【发布时间】:2011-10-30 09:31:15 【问题描述】:我有一个数据表(数据库是 MSSQL):
ID OrderNO PartCode Quantity DateEntered
417 2144 44917 100 18-08-11
418 7235 11762 5 18-08-11
419 9999 60657 100 18-08-11
420 9999 60657 90 19-08-11
我想做一个返回 OrderNO、PartCode 和 Quantity 的查询,但只针对最后注册的订单。
我想从示例表中获取以下信息:
OrderNO PartCode Quantity
2144 44917 100
7235 11762 5
9999 60657 90
请注意,订单 9999 只返回了一行。
谢谢!
【问题讨论】:
从您的评论中选择 ROW_NUMBER() 答案。它可能看起来更长,但根据我的经验,在适当的索引下它是最快的。 感谢 Dems,感谢您的努力。 @GEMI 只是出于好奇,MAX(DATE)
不会为订单 9999 返回一行吗?
是的,但我希望每个不同的订单只返回最后一个订单行。
被***.com/questions/16550703/…和***.com/questions/18393158/…复制
【参考方案1】:
这对我来说非常好。
select name, orderno from (
select name, orderno, row_number() over(partition by
orderno order by created_date desc) as rn from orders
) O where rn =1;
【讨论】:
除了缩进之外,这与 Mikael Eriksson 的回答没有任何区别。【参考方案2】:这对我有用。使用 MAX(CONVERT(date, ReportDate)) 确保您有日期值
select max( CONVERT(date, ReportDate)) FROM [TraxHistory]
【讨论】:
【参考方案3】:如果你有索引 ID 和 OrderNo 你可以使用 IN:(我讨厌交易简单化,只是为了节省一些周期):
select * from myTab where ID in(select max(ID) from myTab group by OrderNo);
【讨论】:
【参考方案4】:rownumber() over(...) 正在工作,但我不喜欢这个解决方案有两个原因。 - 当您使用 SQL2000 等旧版 SQL 时,此功能不可用 - 依赖于函数,不可读。
另一种解决方案是:
SELECT tmpall.[OrderNO] ,
tmpall.[PartCode] ,
tmpall.[Quantity] ,
FROM (SELECT [OrderNO],
[PartCode],
[Quantity],
[DateEntered]
FROM you_table) AS tmpall
INNER JOIN (SELECT [OrderNO],
Max([DateEntered]) AS _max_date
FROM your_table
GROUP BY OrderNO ) AS tmplast
ON tmpall.[OrderNO] = tmplast.[OrderNO]
AND tmpall.[DateEntered] = tmplast._max_date
【讨论】:
【参考方案5】:尽量避免IN使用JOIN
SELECT SQL_CALC_FOUND_ROWS * FROM (SELECT msisdn, callid, Change_color, play_file_name, date_played FROM insert_log
WHERE play_file_name NOT IN('Prompt1','Conclusion_Prompt_1','silent')
ORDER BY callid ASC) t1 JOIN (SELECT MAX(date_played) AS date_played FROM insert_log GROUP BY callid) t2 ON t1.date_played=t2.date_played
【讨论】:
为什么要避免IN?你有什么论据来支持你的观点吗? 执行查询需要很长时间。您可以阅读以下文章xaprb.com/blog/2006/06/28/why-large-in-clauses-are-problematic @anik 这是一篇 2006 年的文章。你最近有什么证据可以证明你在说什么吗?【参考方案6】:select OrderNo,PartCode,Quantity
from dbo.Test t1
WHERE EXISTS(SELECT 1
FROM dbo.Test t2
WHERE t2.OrderNo = t1.OrderNo
AND t2.PartCode = t1.PartCode
GROUP BY t2.OrderNo,
t2.PartCode
HAVING t1.DateEntered = MAX(t2.DateEntered))
这是上面提供的所有查询中最快的。查询成本为 0.0070668。
上面的首选答案,由 Mikael Eriksson 提供,查询成本为 0.0146625
您可能不关心这么小的样本的性能,但在大型查询中,这一切都会加起来。
【讨论】:
在我看来,这在大约 350 万行数据集上比这里的其他解决方案要快一些,但是 SSMS 建议使用一个可以将执行时间减半的索引。谢谢! 快速直接。谢谢。 我有 100k 行,对我来说 Mikael Eriksson 的查询快了 3 倍。也许是因为我在partition by子句中有ROUND函数。 如果您的日期字段具有相同的值 (04/15/2017) 用于 2 个不同的 ID,它将返回 2 行... 是的 Portekoi,这是真的,但是没有任何其他方法来区分这两行,你怎么能选择一个而不是另一个?您可以在结果上放置一个 TOP,但您怎么知道它不是您想要的另一行?【参考方案7】:您也可以使用该选择语句作为左连接查询... 示例:
... left join (select OrderNO,
PartCode,
Quantity from (select OrderNO,
PartCode,
Quantity,
row_number() over(partition by OrderNO order by DateEntered desc) as rn
from YourTable) as T where rn = 1 ) RESULT on ....
希望这对搜索此内容的人有所帮助:)
【讨论】:
【参考方案8】:如果您可以使用ROW_NUMBER()
,最好的方法是 Mikael Eriksson。
根据 Cularis 的回答,下一个最好的方法是加入查询。
另外,最简单直接的方法是在 WHERE 子句中使用相关子查询。
SELECT
*
FROM
yourTable AS [data]
WHERE
DateEntered = (SELECT MAX(DateEntered) FROM yourTable WHERE orderNo = [data].orderNo)
或者……
WHERE
ID = (SELECT TOP 1 ID FROM yourTable WHERE orderNo = [data].orderNo ORDER BY DateEntered DESC)
【讨论】:
【参考方案9】:如果您可以使用rownumber() over(...)
....
select OrderNO,
PartCode,
Quantity
from (select OrderNO,
PartCode,
Quantity,
row_number() over(partition by OrderNO order by DateEntered desc) as rn
from YourTable) as T
where rn = 1
【讨论】:
感谢 Mikael Eriksson,这是一个很棒的查询!【参考方案10】:对于 mysql,您可以执行以下操作:
select OrderNO, PartCode, Quantity from table a
join (select ID, MAX(DateEntered) from table group by OrderNO) b on a.ID = b.ID
【讨论】:
按订单号分组不能在内表中选择ID @Dems 谢谢@cularis 是的,这里指的是MySql,问题没有说明是什么数据库引擎 如果您发布代码、XML 或数据示例,请在文本编辑器中突出显示这些行并单击编辑器上的“代码示例”按钮 (
)工具栏以很好地格式化和语法突出显示它!
这是 MSSQL,抱歉。【参考方案11】:
SELECT t1.OrderNo, t1.PartCode, t1.Quantity
FROM table AS t1
INNER JOIN (SELECT OrderNo, MAX(DateEntered) AS MaxDate
FROM table
GROUP BY OrderNo) AS t2
ON (t1.OrderNo = t2.OrderNo AND t1.DateEntered = t2.MaxDate)
内部查询选择所有OrderNo
及其最大日期。要获取表格的其他列,您可以在 OrderNo
和 MaxDate
上加入它们。
【讨论】:
以上是关于SQL Server:仅选择具有 MAX(DATE) 的行的主要内容,如果未能解决你的问题,请参考以下文章