在同一列中,将每个值与之前的多个值进行条件比较
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
我正在研究 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