TSQL 不常见的查询聚合
TSQL Uncommon query aggregation
我会尽量简短地介绍我的问题。
我有一个 table,其中包含包含每天和类型值的行。我需要 select 更改所有值的类型。我会尝试通过 2 个查询来展示它。
全套看起来像这样:
SELECT *
FROM (
SELECT CONVERT(datetime, '2015-01-01', 120) Date, 0 Type, 0 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-01', 120) Date, 1 Type, 3 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-02', 120) Date, 0 Type, 0 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-02', 120) Date, 1 Type, 3 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-03', 120) Date, 0 Type, 0 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-03', 120) Date, 1 Type, 3 Val1, 7 Val2
UNION SELECT CONVERT(datetime, '2015-01-04', 120) Date, 0 Type, 1 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-04', 120) Date, 1 Type, 4 Val1, 7 Val2
UNION SELECT CONVERT(datetime, '2015-01-05', 120) Date, 0 Type, 1 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-05', 120) Date, 1 Type, 5 Val1, 7 Val2
UNION SELECT CONVERT(datetime, '2015-01-06', 120) Date, 1 Type, 3 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-06', 120) Date, 0 Type, 0 Val1, 5 Val2
) X
ORDER BY 1, 2
现在的想法是这样的,我需要找到 val1 和 val2 发生变化时的所有第一个日期。 val1 和 val2 可以具有与之前某个时间相同的值,因此它是此类型的先前状态的变化。我希望输出是这样的:
SELECT *
FROM (
SELECT CONVERT(datetime, '2015-01-01', 120) Date, 0 Type, 0 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-01', 120) Date, 1 Type, 3 Val1, 5 Val2
--UNION SELECT CONVERT(datetime, '2015-01-02', 120) Date, 0 Type, 0 Val1, 5 Val2
--UNION SELECT CONVERT(datetime, '2015-01-02', 120) Date, 1 Type, 3 Val1, 5 Val2
--UNION SELECT CONVERT(datetime, '2015-01-03', 120) Date, 0 Type, 0 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-03', 120) Date, 1 Type, 3 Val1, 7 Val2
UNION SELECT CONVERT(datetime, '2015-01-04', 120) Date, 0 Type, 1 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-04', 120) Date, 1 Type, 4 Val1, 7 Val2
--UNION SELECT CONVERT(datetime, '2015-01-05', 120) Date, 0 Type, 1 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-05', 120) Date, 1 Type, 5 Val1, 7 Val2
UNION SELECT CONVERT(datetime, '2015-01-06', 120) Date, 1 Type, 3 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-06', 120) Date, 0 Type, 0 Val1, 5 Val2
) X
ORDER BY 1, 2
有什么方法可以在不显着降低性能的情况下使其以这种方式运行?
欢迎您更改结果的排序顺序,但我发现按 Type
分组时更容易理解。
declare @Samples as Table ( EventDate Date, EventType Int, Val1 Int, Val2 Int );
insert into @Samples ( EventDate, EventType, Val1, Val2 ) values
( '2015-01-01', 0, 0, 5 ),
( '2015-01-01', 1, 3, 5 ),
( '2015-01-02', 0, 0, 5 ),
( '2015-01-02', 1, 3, 5 ),
( '2015-01-03', 0, 0, 5 ),
( '2015-01-03', 1, 3, 7 ),
( '2015-01-04', 0, 1, 5 ),
( '2015-01-04', 1, 4, 7 ),
( '2015-01-05', 0, 1, 5 ),
( '2015-01-05', 1, 5, 7 ),
( '2015-01-06', 1, 3, 5 ),
( '2015-01-06', 0, 0, 5 );
select * from @Samples;
with NumberedSamples ( EventOccurrence, EventDate, EventType, Val1, Val2 ) as
( select Row_Number() over ( partition by EventType order by EventDate ) as EventOccurrence,
EventDate, EventType, Val1, Val2
from @Samples ),
StateChanges ( EventOccurrence, EventDate, EventType, Val1, Val2, Skip ) as
( -- Start with the initial Val1/Val2 pair for each Date/Type combination.
select EventOccurrence, EventDate, EventType, Val1, Val2, 0
from NumberedSamples
where EventOccurrence = 1
union all
-- Add each subsequent occurrence for each event and determine whether the values changed.
select NS.EventOccurrence, NS.EventDate, NS.EventType, NS.Val1, NS.Val2,
case when NS.Val1 = SC.Val1 and NS.Val2 = SC.Val2 then 1 else 0 end
from StateChanges as SC inner join
NumberedSamples as NS on NS.EventType = SC.EventType and
NS.EventOccurrence = SC.EventOccurrence + 1 )
select *
from StateChanges
where Skip = 0
order by EventType, EventDate;
我会尽量简短地介绍我的问题。 我有一个 table,其中包含包含每天和类型值的行。我需要 select 更改所有值的类型。我会尝试通过 2 个查询来展示它。
全套看起来像这样:
SELECT *
FROM (
SELECT CONVERT(datetime, '2015-01-01', 120) Date, 0 Type, 0 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-01', 120) Date, 1 Type, 3 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-02', 120) Date, 0 Type, 0 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-02', 120) Date, 1 Type, 3 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-03', 120) Date, 0 Type, 0 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-03', 120) Date, 1 Type, 3 Val1, 7 Val2
UNION SELECT CONVERT(datetime, '2015-01-04', 120) Date, 0 Type, 1 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-04', 120) Date, 1 Type, 4 Val1, 7 Val2
UNION SELECT CONVERT(datetime, '2015-01-05', 120) Date, 0 Type, 1 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-05', 120) Date, 1 Type, 5 Val1, 7 Val2
UNION SELECT CONVERT(datetime, '2015-01-06', 120) Date, 1 Type, 3 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-06', 120) Date, 0 Type, 0 Val1, 5 Val2
) X
ORDER BY 1, 2
现在的想法是这样的,我需要找到 val1 和 val2 发生变化时的所有第一个日期。 val1 和 val2 可以具有与之前某个时间相同的值,因此它是此类型的先前状态的变化。我希望输出是这样的:
SELECT *
FROM (
SELECT CONVERT(datetime, '2015-01-01', 120) Date, 0 Type, 0 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-01', 120) Date, 1 Type, 3 Val1, 5 Val2
--UNION SELECT CONVERT(datetime, '2015-01-02', 120) Date, 0 Type, 0 Val1, 5 Val2
--UNION SELECT CONVERT(datetime, '2015-01-02', 120) Date, 1 Type, 3 Val1, 5 Val2
--UNION SELECT CONVERT(datetime, '2015-01-03', 120) Date, 0 Type, 0 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-03', 120) Date, 1 Type, 3 Val1, 7 Val2
UNION SELECT CONVERT(datetime, '2015-01-04', 120) Date, 0 Type, 1 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-04', 120) Date, 1 Type, 4 Val1, 7 Val2
--UNION SELECT CONVERT(datetime, '2015-01-05', 120) Date, 0 Type, 1 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-05', 120) Date, 1 Type, 5 Val1, 7 Val2
UNION SELECT CONVERT(datetime, '2015-01-06', 120) Date, 1 Type, 3 Val1, 5 Val2
UNION SELECT CONVERT(datetime, '2015-01-06', 120) Date, 0 Type, 0 Val1, 5 Val2
) X
ORDER BY 1, 2
有什么方法可以在不显着降低性能的情况下使其以这种方式运行?
欢迎您更改结果的排序顺序,但我发现按 Type
分组时更容易理解。
declare @Samples as Table ( EventDate Date, EventType Int, Val1 Int, Val2 Int );
insert into @Samples ( EventDate, EventType, Val1, Val2 ) values
( '2015-01-01', 0, 0, 5 ),
( '2015-01-01', 1, 3, 5 ),
( '2015-01-02', 0, 0, 5 ),
( '2015-01-02', 1, 3, 5 ),
( '2015-01-03', 0, 0, 5 ),
( '2015-01-03', 1, 3, 7 ),
( '2015-01-04', 0, 1, 5 ),
( '2015-01-04', 1, 4, 7 ),
( '2015-01-05', 0, 1, 5 ),
( '2015-01-05', 1, 5, 7 ),
( '2015-01-06', 1, 3, 5 ),
( '2015-01-06', 0, 0, 5 );
select * from @Samples;
with NumberedSamples ( EventOccurrence, EventDate, EventType, Val1, Val2 ) as
( select Row_Number() over ( partition by EventType order by EventDate ) as EventOccurrence,
EventDate, EventType, Val1, Val2
from @Samples ),
StateChanges ( EventOccurrence, EventDate, EventType, Val1, Val2, Skip ) as
( -- Start with the initial Val1/Val2 pair for each Date/Type combination.
select EventOccurrence, EventDate, EventType, Val1, Val2, 0
from NumberedSamples
where EventOccurrence = 1
union all
-- Add each subsequent occurrence for each event and determine whether the values changed.
select NS.EventOccurrence, NS.EventDate, NS.EventType, NS.Val1, NS.Val2,
case when NS.Val1 = SC.Val1 and NS.Val2 = SC.Val2 then 1 else 0 end
from StateChanges as SC inner join
NumberedSamples as NS on NS.EventType = SC.EventType and
NS.EventOccurrence = SC.EventOccurrence + 1 )
select *
from StateChanges
where Skip = 0
order by EventType, EventDate;