我有一个简单的三栏表,显示我们的系统上次检查某个网址的日期,以及与该网站相关联的ID编号。
如果我要运行以下查询:
SELECT
SourceId,
Url,
Date
FROM Table1
我最终得到以下结果:
SourceId Url Date
1 www.google.com/abc 2017-10-21
1 www.google.com/def 2017-10-22
1 www.google.com/ghi 2017-10-18
2 www.yahoo.com/123 2017-09-20
2 www.yahoo.com/456 2017-09-27
2 www.yahoo.com/789 2017-10-01
3 www.youtube.com/xyz 2017-07-08
3 www.youtube.com/prs 2017-08-01
3 www.youtube.com/mno 2017-07-16
我需要的是每个源ID只有一个记录,并且它是与该源ID相关联的最新日期;最后,我希望整个列表按源ID按升序排序。因此结果如下:
SourceId Url Date
1 www.google.com/def 2017-10-22
2 www.yahoo.com/789 2017-10-01
3 www.youtube.com/prs 2017-08-01
我知道我必须以ORDER BY SourceId
结束查询。这是我最近遇到麻烦的每个来源的一个记录。我以为我应该在SourceId上使用DISTINCT,但它似乎不起作用,因为它在其他列中寻找重复的值?
编辑 - 更新了网址列中包含错误值的结果。
答案 0 :(得分:3)
您可以使用row_number
窗口函数每个ID仅查询一行:
SELECT [SourceId], [Url], [Date]
FROM (SELECT [SourceId], [Url], [Date],
ROW_NUMBER() OVER (PARTITION BY [SourceId]
ORDER BY [Date] DESC) AS rn
FROM Table1) t
WHERE rn = 1
ORDER BY [SourceId] ASC
答案 1 :(得分:2)
使用NOT EXISTS
SELECT
SourceId,
Url,
Date
FROM Table1 t1
WHERE NOT EXISTS (
SELECT 1
FROM table1 t2
WHERE t1.SourceId = t2.SourceId and t2.date > t1.date
)
ORDER BY SourceId
答案 2 :(得分:2)
您可以将WITH TIES子句与Row_Number()
一起使用示例强>
Select top 1 with ties *
From YourTable
Order By Row_Number() over (Partition By SourceID Order By Date Desc)
<强>返回强>
SourceId Url Date
1 www.google.com/def 2017-10-22
2 www.yahoo.com/789 2017-10-01
3 www.youtube.com/prs 2017-08-01
编辑测试
/*
Drop Table #Temp
Select N
,S = newid()
Into #Temp
From (Select Top 1000000 N=Row_Number() Over (Order By (Select NULL)) From master..spt_values n1, master..spt_values n2) A
*/
Select Top 1 with ties *
from #Temp
Order By Row_Number() over (Partition By left(S,2) Order by N Desc)
Select *
From (
Select *,RN=Row_Number() over (Partition By left(S,2) Order by N Desc)
From #Temp
) A
Where RN=1
结果
Run With Ties RN
1 1.83 5.444
2 1.9 5.444
3 1.913 6.374
4 1.957 5.8
5 1.833 6.244
Avg 1.8866 5.8612
答案 3 :(得分:1)
T-SQL: -
SELECT * FROM
( SELECT *,ROW_NUMBER() OVER (PARTITION BY [SOURCEID] ORDER BY [Date] desc) AS ROW_NUMBER FROM [TABLE1] ) AS ROWS
WHERE ROW_NUMBER = 1
输出: -
答案 4 :(得分:1)
Mureinik的回答显示了我会这样做的方式,而且我也赞成了John Cappelletti的回答,因为我认为它显示了一个有趣的替代结构,即使它的评论引起了一些性能问题。
我只想添加一些东西。首先,您对DISTINCT
无法正常工作的假设是正确的:如果您在其中编写SELECT
语句,其中DISTINCT
适用于所有选择列表中的字段,而不仅仅是一个。如果您需要一组不同的值 plus 一些关于它们的其他信息,那么像DISTINCT
这样的窗口函数应该是您首先想到的。
其次,虽然row_number()
偶尔有用,但我认为这是一个被滥用的功能。当我正在阅读或修改现有查询并看到DISTINCT
时,我立刻想知道查询的原始作者是否真的需要它,或者他/她是否用它来掩盖其他地方的一些可疑逻辑查询,例如使用内部或外部联接,其中semi-join更合适。大多数情况下,后者最终成为现实。当您考虑撰写DISTINCT
时,使用此问题的其他答案中显示的功能,停止并问自己是否可能存在更好的解决方案是值得的。