【问题标题】:In the same column, compare each value with previous multiple values with condition在同一列中,将每个值与之前的多个值与条件进行比较
【发布时间】:2020-12-10 22:50:19
【问题描述】:

我正在处理一张看起来像这样的桌子。实际数据集包含数千个 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 下。在这种情况下,结果应该只返回

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

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

我阅读了很多帖子,例如使用 lag()row_number() over (partition by ... order by ...),但仍然不确定该怎么做。任何帮助表示赞赏!

【问题讨论】:

  • 不要将数据发布为图像,而是发布 DDL 和 DML格式化文本 以便其他人可以复制/粘贴它并为你带来答案。

标签: sql sql-server datetime gaps-and-islands


【解决方案1】:

这将是使用具有日期范围规范的窗口函数的好地方。唉,SQL Server 不支持(还没有?)。

最简单的方法可能是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

【讨论】:

  • 你不认为它应该是t1.value &lt;= t.value - 3,正如 OP 所说的“至少增加了 3”
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2018-05-16
    • 2016-01-22
    • 1970-01-01
    • 2021-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-21
    • 1970-01-01
    相关资源
    最近更新 更多