SQL 差距和孤岛问题与扭曲 - 根据前一个标志的持续时间重置标志
Posted
技术标签:
【中文标题】SQL 差距和孤岛问题与扭曲 - 根据前一个标志的持续时间重置标志【英文标题】:SQL Gaps and Island problem with a twist -- reset a flag based on duration from previous flag 【发布时间】:2019-08-01 19:52:36 【问题描述】:我有一个电话数据集,其中包含客户的通话日期和通话结果(状态)。如果最近一次付费电话已经 >= 5 天,我想为每个售出电话向我的销售代表付款。
下面是我的示例数据集以及我拥有的表格。另外,附上表格的图片,其中包含我拥有的列和我想要的列。彩色唱片是卖出电话;绿色的记录是我想要的,红色的记录是我不想支付的,即使是卖出的电话。
我已经尝试了几个使用窗口函数的版本,但还没有成功。非常感谢任何帮助。
DECLARE @have TABLE
(
CallDate DATE,
Status VARCHAR(10)
);
INSERT INTO @have (CallDate, Status)
values
('2019-01-01', 'unsold'),
('2019-01-02', 'unsold'),
('2019-01-04', 'unsold'),
('2019-01-08', 'sold'),
('2019-01-09', 'sold'),
('2019-01-13', 'unsold'),
('2019-01-14', 'sold'),
('2019-01-19', 'unsold'),
('2019-01-21', 'unsold'),
('2019-01-22', 'sold'),
('2019-01-24', 'unsold'),
('2019-01-25', 'sold'),
('2019-01-29', 'sold'),
('2019-01-30', 'unsold'),
('2019-02-04', 'sold'),
('2019-02-05', 'sold'),
('2019-02-06', 'sold'),
('2019-02-11', 'sold'),
('2019-02-12', 'unsold'),
('2019-02-17', 'sold'),
('2019-02-18', 'unsold'),
('2019-02-19', 'unsold'),
('2019-02-20', 'sold')
;
DECLARE @want TABLE
(
CallDate DATE,
Status VARCHAR(10),
PaidCall int,
Days_Since_Last_Paid_Call int
);
INSERT INTO @want (CallDate, Status, PaidCall, Days_Since_Last_Paid_Call)
values
('2019-01-01', 'unsold', 0, NULL),
('2019-01-02', 'unsold', 0, NULL),
('2019-01-04', 'unsold', 0, NULL),
('2019-01-08', 'sold', 1, NULL),
('2019-01-09', 'sold', 0, 1),
('2019-01-13', 'unsold', 0, NULL),
('2019-01-14', 'sold', 1, 6),
('2019-01-19', 'unsold', 0, NULL),
('2019-01-21', 'unsold', 0, NULL),
('2019-01-22', 'sold', 1, 8),
('2019-01-24', 'unsold', 0, NULL),
('2019-01-25', 'sold', 0, 3),
('2019-01-29', 'sold', 1, 7),
('2019-01-30', 'unsold', 0, NULL),
('2019-02-04', 'sold', 1, 6),
('2019-02-05', 'sold', 0, 1),
('2019-02-06', 'sold', 0, 2),
('2019-02-11', 'sold', 1, 7),
('2019-02-12', 'unsold', 0, NULL),
('2019-02-17', 'sold', 1, 6),
('2019-02-18', 'unsold', 0, NULL),
('2019-02-19', 'unsold', 0, NULL),
('2019-02-20', 'sold', 0, 3)
;
我想在我的表中添加 PaidCall 标志,如下表所示。 Days_Since_Paid_Call 只是为了说明我是如何提出付费电话专栏的。
【问题讨论】:
在 DDL 中你有 Status 但图片上的 Quote 是什么? @nikeshpraj 。 . .这会很昂贵,因为您需要使用递归 CTE。 【参考方案1】:不幸的是,您需要迭代处理数据。一种方法是使用递归 CTE:
with s as (
select h.*, row_number() over (order by calldate) as seqnum
from have h
where status = 'sold'
),
cte as (
select calldate, seqnum, 1 as paidquote, calldate as paidquote_date
from s
where seqnum = 1
union all
select s.calldate, s.seqnum,
(case when s.calldate > dateadd(day, 5, paidquote_date) then 1 else 0 end),
(case when s.calldate > dateadd(day, 5, paidquote_date) then s.calldate else cte.paidquote_date end)
from cte join
s
on s.seqnum = cte.seqnum + 1
)
select h.calldate, h.status, coalesce(cte.paidquote, 0) as paidquote
from have h left join
cte
on h.calldate = cte.calldate
order by h.calldate;
Here 是一个 dbfiddle。
【讨论】:
以上是关于SQL 差距和孤岛问题与扭曲 - 根据前一个标志的持续时间重置标志的主要内容,如果未能解决你的问题,请参考以下文章