Sql 创建由多个列和连续日期分区的序列
我试图弄清楚如何创建一个由多个列划分的序列,其中序列必须重新设置,而另一个(基于日期的)列是不连续的 问题:医院ADT(入院/出院/转院)事件发生在特定时间点,但我们希望将这些事件转化为具有持续时间(时间跨度)的活动,即我们有开始日期,但没有结束日期,这是基于下一个适当的ADT事件。我们已经在代码中实现了这一点,但也希望在SQL中实现这一点以提高性能。e、 g.查找在ICU待了48小时以上的患者 我们需要记录六个不同级别的现场位置的持续时间:设施、护理点、建筑、地板、房间和床 例如:Sql 创建由多个列和连续日期分区的序列,sql,sql-server,sql-server-2005,Sql,Sql Server,Sql Server 2005,我试图弄清楚如何创建一个由多个列划分的序列,其中序列必须重新设置,而另一个(基于日期的)列是不连续的 问题:医院ADT(入院/出院/转院)事件发生在特定时间点,但我们希望将这些事件转化为具有持续时间(时间跨度)的活动,即我们有开始日期,但没有结束日期,这是基于下一个适当的ADT事件。我们已经在代码中实现了这一点,但也希望在SQL中实现这一点以提高性能。e、 g.查找在ICU待了48小时以上的患者 我们需要记录六个不同级别的现场位置的持续时间:设施、护理点、建筑、地板、房间和床 例如: Strea
Stream Event Started Facility PointOfCare ...
1 1 2015-01-01 09:05 Hospital-A ICU
1 2 2015-01-02 13:10 Hospital-A WARD-1
2 3 2015-02-10 12:00 Hospital-A ICU
2 4 2015-02-11 12:00 Hospital-A ICU
2 5 2015-02-12 04:30 Hospital-A WARD-2
Stream Event Started Facility FacilitySequence PointOfCare PointOfCareSequence ...
1 1 2015-01-01 09:05 Hospital-A 1 ICU 1
1 2 2015-01-02 13:10 Hospital-A 2 WARD-1 1
2 3 2015-02-10 12:00 Hospital-A 1 ICU 1
2 4 2015-02-11 12:00 Hospital-A 2 ICU 2
2 5 2015-02-12 04:30 Hospital-A 3 WARD-2 1
Stream Event Started Facility FacilitySequence FacilityStarted FacilityEnded PointOfCare PointOfCareSequence PointOfCareStarted PointOfCareEnded ...
1 1 2015-01-01 09:05 Hospital-A 1 2015-01-01 09:05 2015-01-03 12:00 ICU 1 2015-01-01 09:05 2015-01-02 13:10
1 2 2015-01-02 13:10 Hospital-A 2 2015-01-01 09:05 2015-01-03 12:00 WARD-1 1 2015-01-02 13:10 2015-01-03 12:00
2 3 2015-02-10 12:00 Hospital-A 1 2015-02-10 12:00 <NULL> ICU 1 2015-02-10 12:00 2015-02-12 04:30
2 4 2015-02-11 12:00 Hospital-A 2 2015-02-10 12:00 <NULL> ICU 2 2015-02-10 12:00 2015-02-12 04:30
2 5 2015-02-12 04:30 Hospital-A 3 2015-02-10 12:00 <NULL> WARD-2 1 2015-02-12 04:30 <NULL>
Stream Event Started Facility FacilitySequence PointOfCare PointOfCareSequence ...
3 1 2015-03-01 09:05 Hospital-A 1 ICU 1
3 2 2015-03-02 13:10 Hospital-A 2 WARD-1 1
3 3 2015-03-02 10:00 Hospital-A 3 ICU 2
因此,对于每个事件,我们想知道它们在每个特定的站点位置停留了多长时间。每个流中最后一个活动的结束日期要么为空(仍然是住院患者),要么为患者出院日期
以下是我当前的解决方案:
-- Create a sequence for each site location
INSERT INTO ADT_Activity_Sequence
SELECT
[Stream],
[Event],
[Started],
[Facility],
ROW_NUMBER() OVER (PARTITION BY [Stream],
ISNULL([Facility], [Event])
ORDER BY [Started]) AS [FacilitySequence],
[PointOfCare],
ROW_NUMBER() OVER (PARTITION BY [Stream],
ISNULL([Facility], [Event]),
ISNULL([PointOfCare], [Event])
ORDER BY [Started]) AS [PointOfCareSequence]
-- and so on for all site locations
FROM ADT_Event
INNER JOIN ADT_Stream ON ADT_Event.Stream = Stream.Id
例如:
Stream Event Started Facility PointOfCare ...
1 1 2015-01-01 09:05 Hospital-A ICU
1 2 2015-01-02 13:10 Hospital-A WARD-1
2 3 2015-02-10 12:00 Hospital-A ICU
2 4 2015-02-11 12:00 Hospital-A ICU
2 5 2015-02-12 04:30 Hospital-A WARD-2
Stream Event Started Facility FacilitySequence PointOfCare PointOfCareSequence ...
1 1 2015-01-01 09:05 Hospital-A 1 ICU 1
1 2 2015-01-02 13:10 Hospital-A 2 WARD-1 1
2 3 2015-02-10 12:00 Hospital-A 1 ICU 1
2 4 2015-02-11 12:00 Hospital-A 2 ICU 2
2 5 2015-02-12 04:30 Hospital-A 3 WARD-2 1
Stream Event Started Facility FacilitySequence FacilityStarted FacilityEnded PointOfCare PointOfCareSequence PointOfCareStarted PointOfCareEnded ...
1 1 2015-01-01 09:05 Hospital-A 1 2015-01-01 09:05 2015-01-03 12:00 ICU 1 2015-01-01 09:05 2015-01-02 13:10
1 2 2015-01-02 13:10 Hospital-A 2 2015-01-01 09:05 2015-01-03 12:00 WARD-1 1 2015-01-02 13:10 2015-01-03 12:00
2 3 2015-02-10 12:00 Hospital-A 1 2015-02-10 12:00 <NULL> ICU 1 2015-02-10 12:00 2015-02-12 04:30
2 4 2015-02-11 12:00 Hospital-A 2 2015-02-10 12:00 <NULL> ICU 2 2015-02-10 12:00 2015-02-12 04:30
2 5 2015-02-12 04:30 Hospital-A 3 2015-02-10 12:00 <NULL> WARD-2 1 2015-02-12 04:30 <NULL>
Stream Event Started Facility FacilitySequence PointOfCare PointOfCareSequence ...
3 1 2015-03-01 09:05 Hospital-A 1 ICU 1
3 2 2015-03-02 13:10 Hospital-A 2 WARD-1 1
3 3 2015-03-02 10:00 Hospital-A 3 ICU 2
然后根据序列创建持续时间:
INSERT INTO ADT_Activity_Duration
SELECT
[Stream],
[Event],
[Started],
[Facility],
[Sequence].[FacilitySequence],
(
-- Find most recent activity which is the first in current sequence
SELECT TOP 1 [FacilitySequence].[Started]
FROM [ADT_Activity_Sequence] [FacilitySequence]
WHERE [FacilitySequence].[Stream] = [Event].[Stream] AND [FacilitySequence].[FacilitySequence] = 1 AND [FacilitySequence].[Started] <= [Event].[Started]
ORDER BY [FacilitySequence].[Started] DESC
) AS [FacilityStarted],
(
-- Find first activity in next sequence as this activities end date
-- Last activity returns null, so activity uses stream end date if set
ISNULL((
SELECT TOP 1 [FacilitySequence].[Started]
FROM [ADT_Activity_Sequence] [FacilitySequence]
WHERE [FacilitySequence].[Stream] = [Event].[Stream] AND [FacilitySequence].[FacilitySequence] = 1 AND [FacilitySequence].[Started] > [Event].[Started]
ORDER BY [FacilitySequence].[Started]), [Stream].[Ended])
) AS [FacilityEnded],
[PointOfCare],
[Sequence].[PointOfCareSequence],
(
SELECT TOP 1 [PointOfCareSequence].[Started]
FROM [ADT_Activity_Sequence] [PointOfCareSequence]
WHERE [PointOfCareSequence].[Stream] = [Event].[Stream] AND [PointOfCareSequence].[PointOfCareSequence] = 1 AND [PointOfCareSequence].[Started] <= [Event].[Started]
ORDER BY [PointOfCareSequence].[Started] DESC
) AS [PointOfCareStarted],
(
ISNULL((
SELECT TOP 1 [PointOfCareSequence].[Started]
FROM [ADT_Activity_Sequence] [PointOfCareSequence]
WHERE [PointOfCareSequence].[Stream] = [Event].[Stream] AND [PointOfCareSequence].[PointOfCareSequence] = 1 AND [PointOfCareSequence].[Started] > [Event].[Started]
ORDER BY [PointOfCareSequence].[Started]), [Stream].[Ended])
) AS [PointOfCareEnded]
-- and so on for all site locations
FROM ADT_Event AS [Event]
INNER JOIN [ADT_Stream] AS [Stream] ON [Event].[Stream] = [Stream].[Id]
INNER JOIN [ADT_Activity_Sequence] [Sequence] ON [Event].[Id] = [Sequence].[Event]
例如:
Stream Event Started Facility PointOfCare ...
1 1 2015-01-01 09:05 Hospital-A ICU
1 2 2015-01-02 13:10 Hospital-A WARD-1
2 3 2015-02-10 12:00 Hospital-A ICU
2 4 2015-02-11 12:00 Hospital-A ICU
2 5 2015-02-12 04:30 Hospital-A WARD-2
Stream Event Started Facility FacilitySequence PointOfCare PointOfCareSequence ...
1 1 2015-01-01 09:05 Hospital-A 1 ICU 1
1 2 2015-01-02 13:10 Hospital-A 2 WARD-1 1
2 3 2015-02-10 12:00 Hospital-A 1 ICU 1
2 4 2015-02-11 12:00 Hospital-A 2 ICU 2
2 5 2015-02-12 04:30 Hospital-A 3 WARD-2 1
Stream Event Started Facility FacilitySequence FacilityStarted FacilityEnded PointOfCare PointOfCareSequence PointOfCareStarted PointOfCareEnded ...
1 1 2015-01-01 09:05 Hospital-A 1 2015-01-01 09:05 2015-01-03 12:00 ICU 1 2015-01-01 09:05 2015-01-02 13:10
1 2 2015-01-02 13:10 Hospital-A 2 2015-01-01 09:05 2015-01-03 12:00 WARD-1 1 2015-01-02 13:10 2015-01-03 12:00
2 3 2015-02-10 12:00 Hospital-A 1 2015-02-10 12:00 <NULL> ICU 1 2015-02-10 12:00 2015-02-12 04:30
2 4 2015-02-11 12:00 Hospital-A 2 2015-02-10 12:00 <NULL> ICU 2 2015-02-10 12:00 2015-02-12 04:30
2 5 2015-02-12 04:30 Hospital-A 3 2015-02-10 12:00 <NULL> WARD-2 1 2015-02-12 04:30 <NULL>
Stream Event Started Facility FacilitySequence PointOfCare PointOfCareSequence ...
3 1 2015-03-01 09:05 Hospital-A 1 ICU 1
3 2 2015-03-02 13:10 Hospital-A 2 WARD-1 1
3 3 2015-03-02 10:00 Hospital-A 3 ICU 2
注意:事件#3的注意点顺序为2,这是不正确的,由于事件#2位于不同的位置,需要将其重置回1
我已经兜圈子有一段时间了:)谢谢你的帮助,谢谢 如果我正确理解您的问题,您需要连续的
行号()。您可以使用streamrow_NUMBER()
和单个序列之间的行号差异来生成一个组,在该组上为设施和护理点订购行号
由于这些不是使用设施
和护理点
直接分组的,而是根据顺序进行分组的,因此如果患者再次切换回同一设施或护理点,则会重置顺序
用这样的东西
您可以根据需要根据这些顺序生成日期范围
输出
| Stream | Event | Started | Facility | PointOfCare | StreamSequence | FacilitySequence | PointOfCareSequence |
|--------|-------|----------------------------|------------|-------------|----------------|------------------|---------------------|
| 1 | 1 | January, 01 2015 09:05:00 | Hospital-A | ICU | 1 | 1 | 1 |
| 1 | 2 | January, 02 2015 13:10:00 | Hospital-A | WARD-1 | 2 | 2 | 1 |
| 2 | 3 | February, 10 2015 12:00:00 | Hospital-A | ICU | 1 | 1 | 1 |
| 2 | 4 | February, 11 2015 12:00:00 | Hospital-A | ICU | 2 | 2 | 2 |
| 2 | 5 | February, 12 2015 04:30:00 | Hospital-A | WARD-2 | 3 | 3 | 1 |
| 2 | 6 | February, 12 2015 05:30:00 | Hospital-A | ICU | 4 | 4 | 1 |
您能否澄清所提供的表格中哪些是源数据,哪些是预期结果。另外,请添加一个带有SQL Server版本的标记。我没有添加版本标记,因为它是SQL Server>=2005,但现在已将其添加为基线。如果不清楚,很抱歉,但ADT_事件和ADT_流是源表,ADT_活动表正从它们生成。为了简洁起见,我省略了一些其他代码,但主要是处理要更新的事件和流的内务处理。您能否清楚地显示您的样本数据是什么样子的,以及基于该样本数据的最终结果应该是什么。现在问题中有5个表,其中一些有Stream=3
,一些没有。这令人困惑。关于版本:SQL Server 2012+具有类似于LEAD
和LAG
的功能,这可能会大大有助于计算持续时间。没问题,我将创建一个SQLFIDLE模式和一些测试数据。ughai击败了我:)正在处理,谢谢!我唯一需要改变的是在每个站点位置的CTE分区上添加一个ISNULL检查,如果为null,则使用活动PK,因为位置可能并不总是被设置,所以必须在null.FWIW上重置,进一步的测试发现了另一个问题,我可能没有对此进行充分的解释,但每个站点位置都有一个层次结构,因此,我必须将CTE中的每个较低位置划分为较高级别的位置,因为它们可以共享。例如,ICU的同一个密钥可能位于两个不同的设施中,因此您必须按设施和护理点对护理点位置进行划分,以此类推,划分不同的级别。