Sql-如果日期连接,则合并行
我有一个包含行的表:clientid、startdate和enddate。同一客户ID的日期不能重叠。 如果date连接,我想合并每个客户端的行 表如下所示:Sql-如果日期连接,则合并行,sql,oracle,gaps-and-islands,Sql,Oracle,Gaps And Islands,我有一个包含行的表:clientid、startdate和enddate。同一客户ID的日期不能重叠。 如果date连接,我想合并每个客户端的行 表如下所示: clientid startdate enddate 1 10.10.2017 12.10.2017 1 12.10.2017 13.10.2017 1 13.10.2017 17.10.2017 1 10.11.2017 17.1
clientid startdate enddate
1 10.10.2017 12.10.2017
1 12.10.2017 13.10.2017
1 13.10.2017 17.10.2017
1 10.11.2017 17.11.2017
1 17.11.2017 23.11.2017
1 12.12.2017 14.12.2017
2 10.11.2017 15.11.2017
2 01.12.2017 02.12.2017
2 02.12.2017 05.12.2017
clientid startdate enddate
1 10.10.2017 17.10.2017
1 10.11.2017 23.11.2017
1 12.12.2017 14.12.2017
2 10.11.2017 15.11.2017
2 01.12.2017 05.12.2017
CREATE TABLE client_dates (clientid INT NOT NULL, startdate DATE NOT NULL, enddate DATE NOT NULL);
INSERT INTO client_dates VALUES (1, TRY_PARSE('10.10.2017' AS datetime USING 'en-GB'), TRY_PARSE('12.10.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (1, TRY_PARSE('12.10.2017' AS datetime USING 'en-GB'), TRY_PARSE('13.10.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (1, TRY_PARSE('13.10.2017' AS datetime USING 'en-GB'), TRY_PARSE('17.10.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (1, TRY_PARSE('10.11.2017' AS datetime USING 'en-GB'), TRY_PARSE('17.11.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (1, TRY_PARSE('17.11.2017' AS datetime USING 'en-GB'), TRY_PARSE('23.11.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (1, TRY_PARSE('12.12.2017' AS datetime USING 'en-GB'), TRY_PARSE('14.12.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (2, TRY_PARSE('10.11.2017' AS datetime USING 'en-GB'), TRY_PARSE('15.11.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (2, TRY_PARSE('01.12.2017' AS datetime USING 'en-GB'), TRY_PARSE('02.12.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (2, TRY_PARSE('02.12.2017' AS datetime USING 'en-GB'), TRY_PARSE('05.12.2017' AS datetime USING 'en-GB'));
最终的表格应该如下所示:
clientid startdate enddate
1 10.10.2017 12.10.2017
1 12.10.2017 13.10.2017
1 13.10.2017 17.10.2017
1 10.11.2017 17.11.2017
1 17.11.2017 23.11.2017
1 12.12.2017 14.12.2017
2 10.11.2017 15.11.2017
2 01.12.2017 02.12.2017
2 02.12.2017 05.12.2017
clientid startdate enddate
1 10.10.2017 17.10.2017
1 10.11.2017 23.11.2017
1 12.12.2017 14.12.2017
2 10.11.2017 15.11.2017
2 01.12.2017 05.12.2017
CREATE TABLE client_dates (clientid INT NOT NULL, startdate DATE NOT NULL, enddate DATE NOT NULL);
INSERT INTO client_dates VALUES (1, TRY_PARSE('10.10.2017' AS datetime USING 'en-GB'), TRY_PARSE('12.10.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (1, TRY_PARSE('12.10.2017' AS datetime USING 'en-GB'), TRY_PARSE('13.10.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (1, TRY_PARSE('13.10.2017' AS datetime USING 'en-GB'), TRY_PARSE('17.10.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (1, TRY_PARSE('10.11.2017' AS datetime USING 'en-GB'), TRY_PARSE('17.11.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (1, TRY_PARSE('17.11.2017' AS datetime USING 'en-GB'), TRY_PARSE('23.11.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (1, TRY_PARSE('12.12.2017' AS datetime USING 'en-GB'), TRY_PARSE('14.12.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (2, TRY_PARSE('10.11.2017' AS datetime USING 'en-GB'), TRY_PARSE('15.11.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (2, TRY_PARSE('01.12.2017' AS datetime USING 'en-GB'), TRY_PARSE('02.12.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (2, TRY_PARSE('02.12.2017' AS datetime USING 'en-GB'), TRY_PARSE('05.12.2017' AS datetime USING 'en-GB'));
谢谢您的帮助。您可以将这种逻辑与
sum
aggregate和lag
窗口功能一起使用,如下所示:
select clientid, min(startdate) as startdate, max(enddate) as enddate
from
(
select tt.*, sum(grp) over (order by clientid, startdate) sm
from
(
with t(clientid, startdate, enddate) as
(
select 1, date'2017-10-10', date'2017-10-12' from dual union all
select 1, date'2017-10-12', date'2017-10-13' from dual union all
select 1, date'2017-10-13', date'2017-10-17' from dual union all
select 1, date'2017-11-10', date'2017-11-17' from dual union all
select 1, date'2017-11-17', date'2017-11-23' from dual union all
select 1, date'2017-12-12', date'2017-12-14' from dual union all
select 2, date'2017-11-10', date'2017-11-15' from dual union all
select 2, date'2017-12-01', date'2017-12-02' from dual union all
select 2, date'2017-12-02', date'2017-12-05' from dual
)
select clientid,
decode(nvl(lag(enddate) over
(order by enddate),startdate),startdate,0,1)
as grp, --> means prev. value equals or not
row_number() over (order by clientid, enddate) as rn, startdate, enddate
from t
) tt
order by rn
)
group by clientid, sm
order by clientid, enddate;
CLIENTID STARTDATE ENDDATE
---------- ---------- ----------
1 10.10.2017 17.10.2017
1 10.11.2017 23.11.2017
1 12.12.2017 14.12.2017
2 10.11.2017 15.11.2017
2 01.12.2017 05.12.2017
这是SQL Server语法,与Barbaros的方法相同。为了尽可能做到纯粹,我尝试使用自连接,而不是使用
LAG
,但这无疑会使查询更难阅读
SELECT clientid, MIN(startdate) AS startdate, MAX(enddate) AS enddate
FROM (SELECT *, SUM(CASE WHEN a.enddate_prev = a.startdate THEN 0 ELSE 1 END) OVER (ORDER BY clientid, startdate) sm
FROM (SELECT clientid, startdate, enddate,
LAG(enddate, 1, NULL) OVER (PARTITION BY clientid ORDER BY clientid, enddate) enddate_prev
FROM client_dates) a) b
GROUP BY clientid, sm
如下所示设置表格:
clientid startdate enddate
1 10.10.2017 12.10.2017
1 12.10.2017 13.10.2017
1 13.10.2017 17.10.2017
1 10.11.2017 17.11.2017
1 17.11.2017 23.11.2017
1 12.12.2017 14.12.2017
2 10.11.2017 15.11.2017
2 01.12.2017 02.12.2017
2 02.12.2017 05.12.2017
clientid startdate enddate
1 10.10.2017 17.10.2017
1 10.11.2017 23.11.2017
1 12.12.2017 14.12.2017
2 10.11.2017 15.11.2017
2 01.12.2017 05.12.2017
CREATE TABLE client_dates (clientid INT NOT NULL, startdate DATE NOT NULL, enddate DATE NOT NULL);
INSERT INTO client_dates VALUES (1, TRY_PARSE('10.10.2017' AS datetime USING 'en-GB'), TRY_PARSE('12.10.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (1, TRY_PARSE('12.10.2017' AS datetime USING 'en-GB'), TRY_PARSE('13.10.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (1, TRY_PARSE('13.10.2017' AS datetime USING 'en-GB'), TRY_PARSE('17.10.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (1, TRY_PARSE('10.11.2017' AS datetime USING 'en-GB'), TRY_PARSE('17.11.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (1, TRY_PARSE('17.11.2017' AS datetime USING 'en-GB'), TRY_PARSE('23.11.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (1, TRY_PARSE('12.12.2017' AS datetime USING 'en-GB'), TRY_PARSE('14.12.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (2, TRY_PARSE('10.11.2017' AS datetime USING 'en-GB'), TRY_PARSE('15.11.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (2, TRY_PARSE('01.12.2017' AS datetime USING 'en-GB'), TRY_PARSE('02.12.2017' AS datetime USING 'en-GB'));
INSERT INTO client_dates VALUES (2, TRY_PARSE('02.12.2017' AS datetime USING 'en-GB'), TRY_PARSE('05.12.2017' AS datetime USING 'en-GB'));
你说的“如果日期连接”是什么意思?他的意思是“如果某一行有一个结束日期,即与另一行的开始日期相同,那么它们连接[日期周期继续]”。看10.10.17->12.120.17,但另一行是12->13,所以日期范围实际上是10-13,但另一行是13-17,所以日期范围实际上是10-17。。然后有一个中断,因为没有其他行有不需要的内容result@Simonare是的,你是对的,我现在可以弄明白了。将
解码/nvl
替换为合并/时的情况将使它更适合不同的用户vendors@CaiusJard是的,相当可观。作为一个Oracle的特殊问题,并且由于我喜欢的decode
的简短格式,我更喜欢使用so.case x,当1然后y或者z不如decode那么简短时,但更易于自我记录。。您确实需要添加注释来解释解码的简洁性,因此使用难以理解的代码不会因为代码紧凑而节省太多字符,然后必须添加注释来解释它