记录会定期插入此表中。该ID始终保持不变,但有时值会更改。注意:该值将始终增加。
从此示例数据中:
Create Table Taco
( Taco_ID int,
Taco_value int,
Taco_date datetime)
Insert INTO Taco
Values (1, 1, '2012-07-01 00:00:01'),
(1, 1, '2012-07-01 00:00:02'),
(1, 1, '2012-07-01 00:00:03'),
(1, 1, '2012-07-01 00:00:04'),
(1, 2, '2012-07-01 00:00:05'),
(1, 2, '2012-07-01 00:00:06'),
(1, 2, '2012-07-01 00:00:07'),
(1, 2, '2012-07-01 00:00:08')
结果应为:
Taco_ID Taco_date
1 2012-07-01 00:00:05
(因为00:05是
Taco_Value
的最后一次更改。)#1 楼
这两个查询均基于以下假设:Taco_value
总是随着时间增加。 >更新对于那些跟踪的人,如果可以重复
Taco_value
,将会发生什么是有争议的。如果对于任何给定的Taco_ID
,它可以从1变为2,然后又返回1,则查询将不起作用。对于这种情况,这是一个解决方案,即使它不是Itzik Ben-Gan之类的人可能可以梦想的间隙和孤岛技术,即使它与OP的情况无关-与未来的读者有关。稍微复杂一点,我还添加了一个额外的变量-一个Taco_ID
,该变量只能有一个Taco_value
。 :;WITH x AS
(
SELECT Taco_ID, Taco_date,
dr = ROW_NUMBER() OVER (PARTITION BY Taco_ID, Taco_Value ORDER BY Taco_date),
qr = ROW_NUMBER() OVER (PARTITION BY Taco_ID ORDER BY Taco_date)
FROM dbo.Taco
), y AS
(
SELECT Taco_ID, Taco_date,
rn = ROW_NUMBER() OVER (PARTITION BY Taco_ID, dr ORDER BY qr DESC)
FROM x WHERE dr = 1
)
SELECT Taco_ID, Taco_date
FROM y
WHERE rn = 1;
如果要排除这些行,则要复杂一些,但仍需进行一些细微的更改:
;WITH x AS
(
SELECT Taco_ID, Taco_value, Taco_date = MIN(Taco_date)
FROM dbo.Taco
GROUP BY Taco_ID, Taco_value
), y AS
(
SELECT Taco_ID, Taco_date,
rn = ROW_NUMBER() OVER (PARTITION BY Taco_ID ORDER BY Taco_date DESC)
FROM x
)
SELECT Taco_ID, Taco_date FROM y WHERE rn = 1;
更新了SQLfiddle示例
评论
我注意到OVER存在一些重大的性能问题,但仅使用了几次,可能编写得很差。你有没有注意到?
–肯尼斯·费舍尔
2013年6月18日19:21
@KennethFisher不专门用于OVER。像其他任何东西一样,查询构造在很大程度上依赖于基础架构/索引才能正常工作。分区的over子句将遭受与GROUP BY相同的问题。
–亚伦·伯特兰(Aaron Bertrand)
13年6月18日在19:26
@KennethFisher请注意不要从单个,孤立的观察中得出广泛而笼统的结论。我看到了反对CTE的相同论点-“嗯,我曾经有一次递归CTE,它的性能糟透了。因此,我不再使用CTE。”
–亚伦·伯特兰(Aaron Bertrand)
13年6月18日在19:32
这就是为什么我问。我还没有足够用它来表达一种或另一种方式,但是几次使用它我都能通过CTE获得更好的性能。我会继续玩下去。
–肯尼斯·费舍尔
13年6月18日在19:38
@AaronBertrand我不认为如果重新出现值,这些将不会起作用:小提琴
–超立方体ᵀᴹ
13年6月18日在19:44
#2 楼
基本上,这是@Taryn的建议,“压缩”为没有派生表的单个SELECT:。 (更确切地说,它假设
Taco_value
无法更改回先前的值-实际上与链接的答案相同。)用于查询的SQL Fiddle演示:http://sqlfiddle.com/ #!3/91368/2
评论
哇,嵌套MAX / MIN。心灵吹+1
–亚伦·伯特兰(Aaron Bertrand)
2013年6月19日11:16
#3 楼
您应该能够同时使用min()
和max()
聚合函数来获得结果:select t1.Taco_ID, MAX(t1.taco_date) Taco_Date
from taco t1
inner join
(
select MIN(taco_date) taco_date,
Taco_ID, Taco_value
from Taco
group by Taco_ID, Taco_value
) t2
on t1.Taco_ID = t2.Taco_ID
and t1.Taco_date = t2.taco_date
group by t1.Taco_Id
请参阅带有演示的SQL Fiddle
#4 楼
另一个答案是基于以下假设:这些值不会再次出现(这基本上是@Aaron的查询2,压缩在较少的嵌套中): :SQL-Fiddle并回答一个更普遍的问题,在该问题中值可能重新出现:
CROSS APPLY
,因此显示了所有相关行,包括value
):;WITH x AS
(
SELECT
Taco_ID, Taco_value,
Rn = ROW_NUMBER() OVER (PARTITION BY Taco_ID
ORDER BY MIN(Taco_date) DESC),
Taco_date = MIN(Taco_date)
FROM dbo.Taco
GROUP BY Taco_ID, Taco_value
)
SELECT Taco_ID, Taco_value, Taco_date
FROM x
WHERE Rn = 1 ;
在以下位置进行测试:SQL-Fiddle-2
评论
对于更普遍的问题的建议不适用于没有更改的ID。可以通过在原始集中添加虚拟条目来解决(例如dbo.Taco UNION ALL SELECT DISTINCT Taco_ID,NULL AS Taco_value,'19000101'AS Taco_date)。
– Andriy M
13年6月20日在6:54
@AndriyM我知道。我以为“更改”意味着当至少有2个值时他们想要结果,OP并没有澄清这一点(并且因为编写起来更容易:)
–超立方体ᵀᴹ
2013年6月20日6:56
#5 楼
FYI +1,用于提供样本结构和数据。我唯一想要的就是该数据的预期输出。编辑:这会让我发疯。我只是新手,这是一种“简单”的方法。我摆脱了不正确的解决方案,并提出了一个我认为是正确的解决方案。这是一种类似于@bluefeets的解决方案,但涵盖了@AaronBertrand进行的测试。
;WITH TacoMin AS (SELECT Taco_ID, Taco_value, MIN(Taco_date) InitialValueDate
FROM Taco
GROUP BY Taco_ID, Taco_value)
SELECT Taco_ID, MAX(InitialValueDate)
FROM TacoMin
GROUP BY Taco_ID
评论
OP不要求提供更新日期,而是询问值何时更改。
–超立方体ᵀᴹ
13年6月18日在19:22
啊,我明白了我的错误。我得出了一个答案,但这与@Aaron的答案几乎相同,因此发布它毫无意义。
–肯尼斯·费舍尔
13年6月18日在19:48
#6 楼
为什么不仅仅获得滞后值和提前值之差?如果差为零,则它没有变化,它不是零,那么它就改变了。这可以通过简单的查询完成:-- example gives the times the value changed in the last 24 hrs
SELECT
LastUpdated, [DiffValue]
FROM (
SELECT
LastUpdated,
a.AboveBurdenProbe1TempC - coalesce(lag(a.AboveBurdenProbe1TempC) over (order by ProcessHistoryId), 0) as [DiffValue]
FROM BFProcessHistory a
WHERE LastUpdated > getdate() - 1
) b
WHERE [DiffValue] <> 0
ORDER BY LastUpdated ASC
评论
滞后...仅在SQL Server 2012中“最近”引入了分析功能。最初的问题是在SQL Server 2008 R2上寻求解决方案。您的解决方案不适用于SQL Server 2008 R2。
– John K. N.
18/09/21在9:43
#7 楼
今天有一个类似的问题-在Power BI中,我可以使用Tabler.FillDown解决它。经过一番搜索,我找到了FillDown的SQL变体:https://www.oraylis.de/blog/fill-down-table-in-t-sql-last-non-empty -value
因此,我花时间使该解决方案适应此示例-添加了额外的一行以显示Taco_value的重用。 >注意:此解决方案考虑到Taco_value可以增加和减少(或更改回先前的值)
Insert INTO Taco
Values (1, 1, '2012-07-01 00:00:09')
结果:
#8 楼
SELECT taco_id, MAX(
CASE
WHEN taco_value <> MAX(taco_value)
THEN taco_date
ELSE null
END) AS last_change_date
鉴于taco_value总是增加?
p.s。我本人还是SQL的初学者,但是学习肯定很慢。
评论
在SQL Server上,这会给出错误。无法对包含聚集或子查询的表达式执行聚集功能
–马丁·史密斯
2013年6月19日7:01
在Martin的评论中添加一点:如果您只发布经过测试的代码,那么您会很安全。如果您不在通常的操场上,可以使用一种简单的方法访问sqlfiddle.com。
– dezso
13年6月19日在8:07
评论
我以为玉米卷与食物无关吗?我饿了,想吃一些炸玉米饼。只需为样品表命名。
您是否以类似的方式选择了用户名?
很有可能。