我的表格中有以下行:
Customer Start End 1A 2019-01-01 2019-01-04 1A 2019-01-03 2019-01-06 1A 2019-01-06 2019-01-10 1A 2019-02-01 2019-02-07 2A 2019-03-01 2019-04-05
我需要合并表格,使其看起来像这样:
Customer Start End 1A 2019-01-01 2019-01-10 1A 2019-02-01 2019-02-07 2A 2019-03-01 2019-04-05
我可以在SQL中采取哪些步骤来实现这一目标?
答案 0 :(得分:0)
使用DATEPART(MONTH, DATE)
和MIN()
,MAX()
聚合窗口函数可以达到预期的效果:
SELECT DISTINCT Customer,
MIN(Start) OVER (PARTITION BY Customer, StartMonth) AS Start,
MAX([End]) OVER (PARTITION BY Customer, EndMonth) AS [End]
FROM (
SELECT *, DATEPART(MONTH, Start) AS StartMonth, DATEPART(MONTH, [End]) AS EndMonth
FROM TestTable
) Q
请在db<>fiddle上找到有效的演示。
使用给定的样本数据执行样本:
DECLARE @TestTable TABLE (Customer VARCHAR(2), Start DATE, [End] DATE);
INSERT INTO @TestTable (Customer, Start, [End]) VALUES
('1A', '2019-01-01', '2019-01-04'),
('1A', '2019-01-03', '2019-01-06'),
('1A', '2019-01-06', '2019-01-10'),
('1A', '2019-02-01', '2019-02-07'),
('2A', '2019-03-01', '2019-04-05');
SELECT DISTINCT Customer,
MIN(Start) OVER (PARTITION BY Customer, StartMonth) AS Start,
MAX([End]) OVER (PARTITION BY Customer, EndMonth) AS [End]
FROM (
SELECT *, DATEPART(MONTH, Start) AS StartMonth, DATEPART(MONTH, [End]) AS EndMonth
FROM @TestTable
) Q
答案 1 :(得分:0)
这很棘手。您正在尝试合并期间。查找重叠的一种方法是使用累积max()
。然后使用它来识别组。最后使用聚合:
select customer, min(start), max(end)
from (select t.*,
sum(case when prev_max >= start then 0 else 1 end) over -- beginning of a new period
(partition by customer order by start) as grp
from (select t.*,
max(end) over (partition by customer
order by start
rows between unbounded preceding and 1 preceding
) as prev_max_end
from t
) t
) t
group by customer, grp;
请注意,start
和end
都是SQL Server的保留字,因此它们对于列来说都是很不好的名字。假设您的实际列具有更合适的名称,我没有重命名或转义过它们。
答案 2 :(得分:0)
您也可以使用分组依据。如果您要存储一年以上,那么您也必须考虑这一点。试试这个
DECLARE @TestTable TABLE (Customer VARCHAR(2), Start DATE, [End] DATE);
INSERT INTO @TestTable (Customer, Start, [End]) VALUES
('1A', '2019-01-01', '2019-01-04'),
('1A', '2019-01-03', '2019-01-06'),
('1A', '2019-01-06', '2019-01-10'),
('1A', '2019-02-01', '2019-02-07'),
('2A', '2019-03-01', '2019-04-05'),
('1A', '2020-02-01', '2020-02-07'),
('2A', '2020-03-01', '2020-04-05');
SELECT Customer, MIN(Start), MAX([End]) FROM @TestTable
GROUP By Customer, DATEADD(MONTH, DATEDIFF(MONTH, 0, Start), 0) ,
DATEADD(MONTH, DATEDIFF(MONTH, 0, [End]), 0)