简体   繁体   English

从具有一组日期的缓慢变化的表中选择记录

[英]Selecting records from slowly changing table with a set of dates

I have a slowly changing table,a new row is created each time any of the source fields are changed.我有一个缓慢变化的表,每次更改任何源字段时都会创建一个新行。 Some metadata is added to show when that version was valid.添加了一些元数据以显示该版本何时有效。 This is a simplified example(dates are dd/mm/yyyy format) that doesn't show the fields which have changed.这是一个简化的示例(日期为 dd/mm/yyyy 格式),它不显示已更改的字段。

Startdate开始日期 Enddate结束日期 Currentrecord当前记录 unique id唯一身份 serial_number序列号
15/12/2020 2020 年 15 月 12 日 31/12/2020 2020 年 12 月 31 日 0 0 1 1 2345 2345
15/12/2020 2020 年 15 月 12 日 8/3/2021 2021 年 8 月 3 日 0 0 2 2 1234 1234
19/9/2020 2020 年 9 月 19 日 15/2/2021 15/2/2021 0 0 3 3 2345 2345
15/12/2020 2020 年 15 月 12 日 8/3/2021 2021 年 8 月 3 日 0 0 4 4 3456 3456
9/3/2021 2021 年 9 月 3 日 10/3/2021 2021 年 10 月 3 日 0 0 5 5 3456 3456
16/2/2021 16/2/2021 10/3/2021 2021 年 10 月 3 日 0 0 6 6 2345 2345
9/3/2021 2021 年 9 月 3 日 26/3/2021 26/3/2021 0 0 7 7 1234 1234
27/3/2021 27/3/2021 2/5/2021 2021 年 2 月 5 日 0 0 8 8 1234 1234
11/3/2021 2021 年 11 月 3 日 17/5/2021 2021 年 5 月 17 日 0 0 9 9 3456 3456
3/3/2021 2021 年 3 月 3 日 27/4/2021 27/4/2021 0 0 10 10 4567 4567
20/1/2021 20/1/2021 7/4/2021 2021 年 7 月 4 日 0 0 11 11 5678 5678
3/5/2021 2021 年 3 月 5 日 30/6/2021 2021 年 6 月 30 日 1 1 12 12 1234 1234
25/5/2021 25/5/2021 31/5/2021 2021 年 5 月 31 日 0 0 13 13 2345 2345
8/4/2021 2021 年 8 月 4 日 22/5/2021 22/5/2021 0 0 14 14 5678 5678
1/6/2021 2021 年 1 月 6 日 26/6/2021 26/6/2021 0 0 15 15 2345 2345
18/5/2021 2021 年 5 月 18 日 3/6/2021 2021 年 3 月 6 日 0 0 16 16 3456 3456
27/6/2021 27/6/2021 2/8/2021 2021 年 2 月 8 日 0 0 17 17 2345 2345
28/4/2021 28/4/2021 28/6/2021 28/6/2021 0 0 18 18 4567 4567
23/5/2021 2021 年 5 月 23 日 6/9/2021 2021 年 6 月 9 日 0 0 19 19 5678 5678
4/6/2021 2021 年 4 月 6 日 28/6/2021 28/6/2021 0 0 20 20 3456 3456
29/6/2021 2021 年 6 月 29 日 25/7/2021 25/7/2021 0 0 21 21 3456 3456
3/8/2021 2021 年 3 月 8 日 31/12/9999 9999 年 12 月 31 日 1 1 22 22 2345 2345
26/7/2021 26/7/2021 31/12/9999 9999 年 12 月 31 日 1 1 23 23 3456 3456
15/10/2021 15/10/2021 31/12/9999 9999 年 12 月 31 日 1 1 24 24 4567 4567
7/9/2021 2021 年 7 月 9 日 1/11/2021 2021 年 1 月 11 日 0 0 25 25 5678 5678
22/9/2021 22/9/2021 10/11/2021 2021 年 10 月 11 日 0 0 26 26 6789 6789
2/11/2021 2021 年 2 月 11 日 16/11/2021 2021 年 11 月 16 日 0 0 27 27 5678 5678
17/11/2021 2021 年 11 月 17 日 21/11/2021 21/11/2021 0 0 28 28 5678 5678
15/7/2021 15/7/2021 31/12/9999 9999 年 12 月 31 日 1 1 29 29 7891 7891
22/11/2021 22/11/2021 31/12/9999 9999 年 12 月 31 日 1 1 30 30 5678 5678
26/11/2021 26/11/2021 31/12/9999 9999 年 12 月 31 日 1 1 31 31 6789 6789
15/6/2021 15/6/2021 31/12/9999 9999 年 12 月 31 日 1 1 32 32 8912 8912

There is only one record for each serial_number for any given point in time (ie the dates ranges will not overlap for identical serial_numbers) but there might be gaps between episodes for a some serial_numbers (representing something leaving and returning after a gap in service).对于任何给定的时间点,每个序列号只有一条记录(即,相同序列号的日期范围不会重叠),但某些序列号的剧集之间可能存在间隔(表示在服务间隔后离开和返回的东西)。

I want to supply an arbitrary list of datetimes, say midnight on 01/01/2021, 15/03/2021, 27/05/2021.我想提供任意日期时间列表,例如 2021 年 1 月 1 日、2021 年 3 月 15 日、2021 年 5 月 27 日午夜。 23/10/2021. 2021 年 10 月 23 日。 I want to return a set of records, containing every record which was in effect on each of the dates, with each row labelled with the date it was selected by.我想返回一组记录,其中包含在每个日期有效的每条记录,每一行都标有它被选中的日期。 So the above example should return this.所以上面的例子应该返回这个。

date日期 unique id唯一身份 serial_number序列号
1/1/2021 2021 年 1 月 1 日 2 2 1234 1234
1/1/2021 2021 年 1 月 1 日 3 3 2345 2345
1/1/2021 2021 年 1 月 1 日 4 4 3456 3456
15/3/2021 2021 年 15 月 3 日 7 7 1234 1234
15/3/2021 2021 年 15 月 3 日 9 9 3456 3456
15/3/2021 2021 年 15 月 3 日 10 10 4567 4567
15/3/2021 2021 年 15 月 3 日 11 11 5678 5678
27/5/2021 27/5/2021 12 12 1234 1234
27/5/2021 27/5/2021 13 13 2345 2345
27/5/2021 27/5/2021 16 16 3456 3456
27/5/2021 27/5/2021 18 18 4567 4567
27/5/2021 27/5/2021 19 19 5678 5678
23/10/2021 2021 年 10 月 23 日 22 22 2345 2345
23/10/2021 2021 年 10 月 23 日 23 23 3456 3456
23/10/2021 2021 年 10 月 23 日 24 24 4567 4567
23/10/2021 2021 年 10 月 23 日 25 25 5678 5678
23/10/2021 2021 年 10 月 23 日 26 26 6789 6789
23/10/2021 2021 年 10 月 23 日 29 29 7891 7891
23/10/2021 2021 年 10 月 23 日 32 32 8912 8912

I can see how to do this with a cursor, stepping through each date putting them into a variable and using something like我可以看到如何使用 cursor 执行此操作,逐步将每个日期放入变量中并使用类似

select @date, [unique id], serial_number
from example
where @date between start_date and end_date

to get the rows.获取行。

I can't work out a pattern that would do it in a set based approach.我无法制定出一种以基于集合的方法进行的模式。 My preferred SQL version is TSQL.我首选的 SQL 版本是 TSQL。 Sorry as this is almost certainly a repeat, but I can't find a form of words that hits a worked example.抱歉,这几乎可以肯定是重复的,但我找不到能打出有效示例的单词形式。

You can use a temporary table to accomplish this.您可以使用临时表来完成此操作。

CREATE TABLE #RequestedDates([Date] DATE)

You insert your dates you want into a temporary table.您将所需的日期插入到临时表中。

INSERT INTO #RequestedDates([Date])
VALUES ('2021-01-01'), ('2021-03-15') /*Other dates*/

And then you join with the temporary table and use the between clause to get the valid results.然后加入临时表并使用 between 子句获得有效结果。

SELECT rd.[Date]
  , t.UniqueId
  , t.SerialNumber
FROM MyTable t
INNER JOIN #RequestedDates rd on rd.[Date] BETWEEN t.StartDate AND t.EndDate
ORDER BY rd.[Date]
  , t.UniqueId
  , t.SerialNumber

You can join to VALUES with the dates you need.您可以在需要的日期加入VALUES
Then join the datetimes on the range.然后加入范围内的日期时间。

SELECT 
  datetimes.dt as [date] 
, t.[unique id] 
, t.serial_number
FROM example t
JOIN (VALUES
 (cast('2021-01-01 00:00:00' as datetime)), 
 ('2021-03-15 00:00:00'), 
 ('2021-05-27 00:00:00'), 
 ('2021-10-23 00:00:00')
) datetimes(dt) 
  ON datetimes.dt >= t.start_date
 AND datetimes.dt <= t.end_date
ORDER BY datetimes.dt, t.[unique id], t.serial_number 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM