Sql server T-SQL删除“重复/不感兴趣”的数据行
我提供了以下一组数据样本Sql server T-SQL删除“重复/不感兴趣”的数据行,sql-server,tsql,sql-server-2012,Sql Server,Tsql,Sql Server 2012,我提供了以下一组数据样本 ID Status Code Type ModDate 1234 1 1 AB 1995-04-01 1234 1 1 CD 1998-08-31 1234 1 1 AB 2003-08-31 1234 1 NULL AB 2008-11-08
ID Status Code Type ModDate
1234 1 1 AB 1995-04-01
1234 1 1 CD 1998-08-31
1234 1 1 AB 2003-08-31
1234 1 NULL AB 2008-11-08
1234 1 2 AB 2013-11-09
1234 1 1 EF 2013-11-18
...
由于必须在某种时间线上查看这些数据,因此我只想从数据库中阅读以下内容,因为只有类型更改才有意义:
ID Status Code Type ModDate
1234 1 1 AB 1995-04-01
1234 1 1 CD 1998-08-31
1234 1 1 AB 2003-08-31
1234 1 1 EF 2013-11-18
...
如何做到这一点?我试图对数据进行分区并给出一些行号,但由于类型是分组的,这让我很头疼
SELECT
ID, Status, Code, Type, ModDate,
MIN(ModDate) OVER (PARTITION BY ID, Type) MinModDate,
MAX(ModDate) OVER (PARTITION BY ID, Type) MaxModDate,
ROW_NUMBER() OVER (PARTITION BY ID, Type ORDER BY ModDate) RowNumber
FROM Data
输出:
ID Status Code Type ModDate MinModDate MaxModDate RowNumber
1234 1 1 AB 1995-04-01 1995-04-01 2013-11-09 1
1234 1 1 CD 1998-08-31 1998-08-31 1998-08-31 1
1234 1 1 AB 2003-08-31 1995-04-01 2013-11-09 2
1234 1 NULL AB 2008-11-08 1995-04-01 2013-11-09 3
1234 1 2 AB 2013-11-09 1995-04-01 2013-11-09 4
1234 1 1 EF 2013-11-18 2013-11-18 2013-11-18 1
...
预期产出:
ID Status Code Type ModDate MinModDate MaxModDate RowNumber
1234 1 1 AB 1995-04-01 1995-04-01 2013-11-09 1
1234 1 1 CD 1998-08-31 1998-08-31 1998-08-31 1
1234 1 1 AB 2003-08-31 1995-04-01 2013-11-09 1
1234 1 NULL AB 2008-11-08 1995-04-01 2013-11-09 2
1234 1 2 AB 2013-11-09 1995-04-01 2013-11-09 3
1234 1 1 EF 2013-11-18 2013-11-18 2013-11-18 1
...
不使用游标可以轻松实现这一点吗?如果我理解正确,您只需要包装原始SQL:
SELECT ID, Status, Code, Type, ModDate FROM
(
SELECT
ID, Status, Code, Type, ModDate,
MIN(ModDate) OVER (PARTITION BY ID, Type) MinModDate,
MAX(ModDate) OVER (PARTITION BY ID, Type) MaxModDate,
ROW_NUMBER() OVER (PARTITION BY ID, Type ORDER BY ModDate) RowNumber
FROM Data
) t
WHERE ModDate=MinModDate
对数据进行分区是您想要的,您只需要按类型进行分区,因为这是您感兴趣的唯一变化。您还需要添加ROW_NUMBER函数以过滤所需的行。这里有一个更新的查询
;WITH cte AS
(
SELECT ID, [Status], Code, [Type], ModDate
,rn = ROW_NUMBER() OVER (PARTITION BY ModDate ORDER BY ModDate)
FROM #data
)
SELECT ID, [Status], Code, [Type], ModDate
FROM cte
WHERE rn = 1
ORDER BY ModDate, [Type]
既然您使用2012,那么这应该可以:
SELECT ID, Status, Code, Type, ModDate FROM
(
SELECT
ID, Status, Code, Type, ModDate,
lag(type,1) OVER (ORDER BY ID, moddate) prevtype
FROM data
)t WHERE type<>ISNULL(prevtype,'')
如果按ID和类型进行分区,那么为什么预期输出的第二、第三和第四行不会得到1、2、3行编号?该分区将在TYPE=AB的所有行上工作,并随后应用排序。这就是为什么第三行的RowNumber=2,而不是1,但这很好,因为我可以按RowNumber=1oh进行筛选,您可以按相同的顺序放置RowNumber。明白了。您使用的是sql server 2012吗?是的,sql server 2012与此语句一起使用,包含数据1234 1 AB 2003-08-31的行与此语句一起丢失,包含数据1234 1 AB 2003-08-31的行丢失如果您感兴趣的是Type by Mod,为什么要包含该AB行?根据数据还不清楚。我想在时间轴上显示类型列中的更改,当然可以将类型更改回以前的值,也可以使用相同的值再次保存记录。我试着忽略这些相同的值。我明白了。那么时间线过滤器是什么?如果同一天有两个相同类型的条目呢?然后,您是否需要查看ModDate的秒数并获取最近的秒数?为了简化,我删除了模式日期的时间部分,但它是一个日期时间类型的列现在第一行缺少1234 1 AB 1995-04-01。是因为在这种情况下没有前一行吗?我在我的机器上测试了它,第一行就在那里。isnullprevtype应该在没有前一行时进行保护。内部选择是正确的,但我需要修改prevType的外部WHERE语句为NULL或类型prevType。我接受你的回答,认为这对解决我的问题最有帮助。你可以使用WHERE-ISNULLType,PrevType-notnull来避免关心Type是否是字符串