在同一列中,将每个值与之前的多个值进行条件比较

In the same column, compare each value with previous multiple values with condition

我正在研究 table 看起来像这样的东西。实际数据集包含数千个 Guest_ID,我在这里只展示了几个样本行。

Guest_ID Visit_ID Collection_time Value
6 a178 2007-11-09 11:28:00 2.6
6 a188 2007-11-10 20:28:00 6.6
12 a278 2008-11-11 10:28:00 2.7
12 a278 2008-11-11 11:38:00 3.2
12 a278 2008-11-12 11:48:00 6.8
12 c348 2009-10-12 11:38:00 3.8
15 e179 2013-01-15 09:25:00 1.8
15 e179 2013-01-15 10:26:00 1.6
15 e179 2013-01-15 12:15:00 3.8
15 e179 2013-01-17 09:25:00 3.6

这里我想做的是找出在过去48小时内至少增加了3的值,并且这些值需要在相同的visit_id之下。在这种情况下,结果应该只有 return

Guest_ID Visit_ID Collection_time Value
12 a278 2008-11-12 11:48:00 6.8

我对在 SQL 服务器中创建孤岛和间隙有一些模糊的想法,但不确定如何处理它。从概念上讲,对于每个值 X,我需要提取所有先前的值满足条件(在过去 48 小时内并且在相同的 Visit_ID 下),然后检查 X - min(previous value) >= 3。如果是, 保留或标记 X 为 1, 并重复该过程。

我阅读了很多帖子,例如使用 lag()row_number() over (partition by ... order by ...),但仍然不确定该怎么做。感谢您的帮助!

这里是使用具有日期范围规范的 window 函数的好地方。唉,SQL 服务器不支持(还?)。

最简单的方法可能是 exists 和一个相关的子查询:

select t.*
from mytable t
where exists (
    select 1
    from mytable t1
    where 
        t1.visit_id = t.visit_id 
        and t1.collection_time >= dateadd(day, -2.collection_time)
        and t1.collection_time <  t.collection_time
        and t1.value < t.value - 3
)

或者您可以使用 cross apply:

select t.*
from mytable t
cross apply (
    select min(t1.value) as min_value
    from mytable t1
    where 
        t1.visit_id = t.visit_id 
        and t1.collection_time >= dateadd(day, -2.collection_time)
        and t1.collection_time <  t.collection_time
) t1
where t1.min_value < t.value - 3

我使用 CTE 首先过滤掉符合条件的行,然后将其加入原始 table 以获取这些行:

CREATE TABLE #tmp(Guest_ID int, Visit_ID varchar(10),   Collection_time datetime,   Value decimal(10,1))
INSERT INTO #tmp VALUES
(6, 'a178', '2007-11-09 11:28:00',  2.6),
(6, 'a188', '2007-11-10 20:28:00',  6.6),
(12,    'a278', '2008-11-11 10:28:00',  2.7),
(12,    'a278', '2008-11-11 11:38:00',  3.2),
(12,    'a278', '2008-11-12 11:48:00',  6.8),
(12,    'c348', '2009-10-12 11:38:00',  3.8),
(15,    'e179', '2013-01-15 09:25:00',  1.8),
(15,    'e179', '2013-01-15 10:26:00',  1.6),
(15,    'e179', '2013-01-15 12:15:00',  3.8),
(15,    'e179', '2013-01-17 09:25:00',  3.6)


;WITH CTE AS(
    SELECT MAX(Collection_time) MaxCollection_Time, Max(Value) - Min(Value) DiffInValue ,Visit_ID 
    FROM #tmp
    GROUP BY Visit_ID
    HAVING Max(Value) - Min(Value) >= 3
    )
SELECT t1.*
FROM #tmp t1
INNER JOIN CTE t2 on t1.Visit_ID = t2.Visit_ID and T1.Collection_time = t2.MaxCollection_Time