SQL 查询列,如果在 "chain" 行内满足条件则为真
TSQL Query column which is true if condition is met within "chain" of rows
这是 的跟进。这会变得复杂。
我有一个如下所示的 table 用于跟踪特定类型事件的开始和结束:
+----------+-------------+------------------+------------------+
| PersonID | Weapon Used | StartDate | EndDate |
+----------+-------------|------------------+------------------+
| 006 | Knife | 2019-12-01 09:30 | 2019-12-02 06:15 |
| 007 | Grenade | 2019-12-01 12:15 | 2019-12-01 12:16 |
| 006 | Bat | 2019-12-02 06:15 | 2019-12-02 15:15 |
| 006 | Pistol | 2019-12-02 15:15 | 2019-12-02 23:01 |
| 007 | Pistol | 2019-12-02 07:23 | 2019-12-04 08:30 |
+----------+-------------+------------------+------------------+
我正在尝试创建一个在以下条件下returns TRUE 的计算列:
- 行事件是 "chain" 1+ 背靠背事件的一部分。
- AND 手枪在事件链中使用了 1 次以上。
- AND 行事件具有链中最早的 StartDate。
像这样创建 table:
+----------+-------------+------------------+------------------+---------+
| PersonID | Weapon Used | StartDate | EndDate | Pistol+ |
+----------+-------------|------------------+------------------+---------+
| 006 | Knife | 2019-12-01 09:30 | 2019-12-02 06:15 | TRUE |
| 007 | Grenade | 2019-12-01 12:15 | 2019-12-01 12:16 | FALSE |
| 006 | Bat | 2019-12-02 06:15 | 2019-12-02 15:15 | FALSE |
| 006 | Pistol | 2019-12-02 15:15 | 2019-12-02 23:01 | FALSE |
| 007 | Pistol | 2019-12-02 07:23 | 2019-12-04 08:30 | TRUE |
+----------+-------------+------------------+------------------+---------+
这确实是一项艰巨的任务,但我必须为大量的行执行此任务,因此我拼命地避免必须用手和眼球来计算它。这可能吗?
您将需要 recursive cte
找到 grp
相关的连续行
seq
是识别第一个的group
为了识别组是否包含 pistol
,它使用 window 函数 sum()
和条件 case
with
cte as
(
select *, rn = row_number() over (partition by PersonID order by StartDate)
from yourtable
),
rcte as
(
select c.PersonID, c.[Weapon Used], c.StartDate, c.EndDate, c.rn,
grp = 1, seq = 1
from cte c
where rn = 1
union all
select c.PersonID, c.[Weapon Used], c.StartDate, c.EndDate, c.rn,
grp = case when r.EndDate = c.StartDate
then r.grp
else r.grp + 1
end,
seq = case when r.EndDate = c.StartDate
then r.seq + 1
else 1
end
from cte c
inner join rcte r on c.PersonID = r.PersonID
and c.rn = r.rn + 1
)
select *,
case when seq = 1
and sum(case when [Weapon Used] = 'Pistol' then 1 else 0 end)
over (partition by PersonID, grp) >= 1
then 'TRUE'
else 'FALSE'
end
from rcte;
这是
我有一个如下所示的 table 用于跟踪特定类型事件的开始和结束:
+----------+-------------+------------------+------------------+
| PersonID | Weapon Used | StartDate | EndDate |
+----------+-------------|------------------+------------------+
| 006 | Knife | 2019-12-01 09:30 | 2019-12-02 06:15 |
| 007 | Grenade | 2019-12-01 12:15 | 2019-12-01 12:16 |
| 006 | Bat | 2019-12-02 06:15 | 2019-12-02 15:15 |
| 006 | Pistol | 2019-12-02 15:15 | 2019-12-02 23:01 |
| 007 | Pistol | 2019-12-02 07:23 | 2019-12-04 08:30 |
+----------+-------------+------------------+------------------+
我正在尝试创建一个在以下条件下returns TRUE 的计算列:
- 行事件是 "chain" 1+ 背靠背事件的一部分。
- AND 手枪在事件链中使用了 1 次以上。
- AND 行事件具有链中最早的 StartDate。
像这样创建 table:
+----------+-------------+------------------+------------------+---------+
| PersonID | Weapon Used | StartDate | EndDate | Pistol+ |
+----------+-------------|------------------+------------------+---------+
| 006 | Knife | 2019-12-01 09:30 | 2019-12-02 06:15 | TRUE |
| 007 | Grenade | 2019-12-01 12:15 | 2019-12-01 12:16 | FALSE |
| 006 | Bat | 2019-12-02 06:15 | 2019-12-02 15:15 | FALSE |
| 006 | Pistol | 2019-12-02 15:15 | 2019-12-02 23:01 | FALSE |
| 007 | Pistol | 2019-12-02 07:23 | 2019-12-04 08:30 | TRUE |
+----------+-------------+------------------+------------------+---------+
这确实是一项艰巨的任务,但我必须为大量的行执行此任务,因此我拼命地避免必须用手和眼球来计算它。这可能吗?
您将需要 recursive cte
找到 grp
相关的连续行
seq
是识别第一个的group
为了识别组是否包含 pistol
,它使用 window 函数 sum()
和条件 case
with
cte as
(
select *, rn = row_number() over (partition by PersonID order by StartDate)
from yourtable
),
rcte as
(
select c.PersonID, c.[Weapon Used], c.StartDate, c.EndDate, c.rn,
grp = 1, seq = 1
from cte c
where rn = 1
union all
select c.PersonID, c.[Weapon Used], c.StartDate, c.EndDate, c.rn,
grp = case when r.EndDate = c.StartDate
then r.grp
else r.grp + 1
end,
seq = case when r.EndDate = c.StartDate
then r.seq + 1
else 1
end
from cte c
inner join rcte r on c.PersonID = r.PersonID
and c.rn = r.rn + 1
)
select *,
case when seq = 1
and sum(case when [Weapon Used] = 'Pistol' then 1 else 0 end)
over (partition by PersonID, grp) >= 1
then 'TRUE'
else 'FALSE'
end
from rcte;