昨天,我在这里发布了这个问题:MSSQL 2008: Get last updated record by specific field
戈登·林诺夫提出了一个很好的解决方案,直到今天我才开心,当时我意识到我只发布了一半的情景。这是我的新问题:
鉴于此表Content
:
ContentId lastUpdate FileId IrrelevantField
1 2014-01-01 00:00:00 File-A Dr. Hoo /* user uploads file*/
1 2014-01-02 00:00:00 File-B Dr. Hoo /* (!) user uploads new file */
1 2014-01-03 00:00:00 File-B Dr. Who /* user updates info */
2 2014-02-01 00:00:00 File-M 41 /* (!) user uploads file */
2 2014-02-02 00:00:00 File-M 42 /* user updates info */
3 2014-03-01 00:00:00 File-S Donald Duck /* user uploads file*/
基本上我想要的是获得满足这些条件的所有行:
FileId
与ContentId
相同。FileId
从未更改,请获取第一个提交的行(这在示例中适用于ContentId
= 2& 3.) IrrelevantField
触发行更新。我的目标是,在FileId
发生变化时获取行。
输出结果如下:
ContentId lastUpdate FileId IrrelevantField
1 2014-01-02 00:00:00 File-B Dr. Hoo
2 2014-02-01 00:00:00 File-M 41
3 2014-03-01 00:00:00 File-S Donald Duck
FileId
永远不会NULL
。
我尝试向Gordon Linoff的解决方案添加OUTER APPLY
,因此我可以检查FileId
是否仍与初始上传时相同。但这也让我无关紧要的更新。
答案 0 :(得分:2)
尝试这应该适用于所有场景..
;with cte
as
(
select rank() over(partition by fileid,contentid order by lastupdate ) id, ContentId,lastUpdate,FileId,IrrelevantField from tablename
)
select ContentId,lastUpdate,FileId,IrrelevantField from(
select row_number() over(partition by contentid order by lastupdate desc) fstid, * from cte where id=1) a where fstid=1
答案 1 :(得分:2)
您沿着正确的路线将其更改为外部申请,然后您可以稍微更改WHERE
子句以允许记录没有先前记录的记录。
SELECT c.ContentID,
c.LastUpdate,
c.FileID,
c.IrrelevantField,
FileID2 = c2.FileID
FROM Content AS c
OUTER APPLY
( SELECT TOP 1 c2.FileID
FROM Content AS c2
WHERE c2.ContentID = c.ContentID
AND c2.LastUpdate < c.LastUpdate
ORDER BY c2.LastUpdate DESC
) AS c2
WHERE c.FileId != c2.FileId
OR c2.FileID IS NULL;
这意味着虽然为ContentID = 1(以及任何其他包含更改的内容)返回了两条记录:
ContentID LastUpdate FileID IrrelevantField FileID2
1 2014-01-01 File-A Dr. Hoo NULL
1 2014-01-02 File-B Dr. Hoo File-A
2 2014-02-01 File-M 41 NULL
3 2014-03-01 File-S Donald Duck NULL
因此,您需要使用进一步的排名功能将此限制为仅限最新记录:
WITH CTE AS
( SELECT c.ContentID,
c.LastUpdate,
c.FileID,
c.IrrelevantField,
RowNumber = ROW_NUMBER() OVER(PARTITION BY c.ContentID ORDER BY c.LastUpdate DESC)
FROM Content AS c
OUTER APPLY
( SELECT TOP 1 c2.FileID
FROM Content AS c2
WHERE c2.ContentID = c.ContentID
AND c2.LastUpdate < c.LastUpdate
ORDER BY c2.LastUpdate DESC
) AS c2
WHERE c.FileId != c2.FileId
OR c2.FileID IS NULL
)
SELECT c.ContentID,
c.LastUpdate,
c.FileID,
c.IrrelevantField
FROM CTE AS c
WHERE RowNumber = 1;
答案 2 :(得分:1)
下面的查询使用lead
创建一个派生表,其中包含FileId已更改的所有行以及第1行。然后,如果没有针对该ContentId(row_number()
)更改的FileId或FileId已更改的所有其他行(rn_asc = 1 and rn_desc = 1
),则使用rn_asc > 1
显示第1行。如果您只想要更改FileId的第一行,请使用rn_asc = 2
代替rn_asc > 1
。
select * from (
select * ,
row_number() over (partition by ContentId order by lastUpdate asc) rn_asc,
row_number() over (partition by ContentId order by lastUpdate desc) rn_desc
from (
select *
from (
select * ,
lead(FileId) over (partition by ContentId order by lastUpdate) previousFileId
from content c
) t1 where previousFileId <> FileId or previousFileId IS NULL
) t2
) t3 where (rn_asc = 1 and rn_desc = 1) or rn_asc > 1
答案 3 :(得分:0)
select ContentId, lastUpdate, FileId, IrrelevantField
from (
select row_number() over(partition by contentid order by lastupdate desc) LastChgsl, *
from
(
select
row_number() over(partition by fileid order by lastupdate) FileChgSl, *
from tablename
)V where FileChgSl = 1
)V1 where LastChgsl = 1