我有三个表:每种类型的服务一个。每个表都列出了不同日期的特定服务的客户价格:
TABLE: SERVICE_A
| StartDate | EndDate | Price |
----------------------------------------
| 01/01/2013 | 16/04/2013 | 30 |
| 17/04/2013 | 20/09/2013 | 33 |
| 21/09/2013 | 31/12/2013 | 34 |
TABLE: SERVICE_B
| StartDate | EndDate | Price |
----------------------------------------
| 01/01/2013 | 30/06/2013 | 47 |
| 01/07/2013 | 31/12/2013 | 49 |
TABLE: SERVICE_C
| StartDate | EndDate | Price |
----------------------------------------
| 01/01/2013 | 03/03/2013 | 96 |
| 04/03/2013 | 31/12/2013 | 101 |
我正在尝试创建一个合并此数据的表,并重新构建它以显示适当日期范围内所有三种服务的价格:
RESULTS
| StartDate | EndDate | PriceA | PriceB | PriceC |
----------------------------------------------------------
| 01/01/2013 | 03/03/2013 | 30 | 47 | 96 |
| 04/03/2013 | 16/04/2013 | 30 | 47 | 101 |
| 17/04/2013 | 30/06/2013 | 33 | 47 | 101 |
| 01/07/2013 | 20/09/2013 | 33 | 49 | 101 |
| 21/09/2013 | 31/12/2013 | 34 | 49 | 101 |
非常感谢您对此查询的任何帮助! (我正在使用SQL Server 2008 R2)。
答案 0 :(得分:0)
这应该这样做。我考虑到在开始日期你有三个价格:
CREATE TABLE #Services (
StartDate DATETIME
, EndDate DATETIME
, PriceA INT
, PriceB INT
, PriceC INt
)
DECLARE @startDt DateTime, @endDt DateTime, @Price Int, @Service Char(1)
DECLARE @PriceA Int, @PriceB Int, @PriceC Int, @previousStartDate DateTime, @finalEndDate DateTime
SET @previousStartDate = '20130101'
DECLARE cursorDatePrices CURSOR FOR
SELECT StartDate, EndDate, Price, 'A' as Service
FROM #SA
UNION ALL
SELECT StartDate, EndDate, Price, 'B' as Service
FROM #SB
UNION ALL
SELECT StartDate, EndDate, Price, 'C' as Service
FROM #SC
ORDER BY StartDate
OPEN cursorDatePrices
FETCH NEXT FROM cursorDatePrices
INTO @startDt, @endDt, @Price, @Service
WHILE @@FETCH_STATUS = 0
BEGIN
--only insert after having the three prices
IF (@PriceA IS NOT NULL AND @PriceB IS NOT NULL AND @PriceC IS NOT NULL)
BEGIN
INSERT INTO #Services VALUES (@previousStartDate, DATEADD(dd, -1, @startDt), @PriceA, @PriceB, @PriceC)
SET @previousStartDate = @startDt
END
IF (@Service = 'A') SET @PriceA = @Price
ELSE IF (@Service = 'B') SET @PriceB = @Price
ELSE IF (@Service = 'C') SET @PriceC = @Price
FETCH NEXT FROM cursorDatePrices
INTO @startDt, @endDt, @Price, @Service
END
CLOSE cursorDatePrices
DEALLOCATE cursorDatePrices
INSERT INTO #Services VALUES (@previousStartDate, @endDt, @PriceA, @PriceB, @PriceC)
SELECT * from #Services
答案 1 :(得分:0)
这是一个可怕的解决方案,但它没有使用游标:D
首先,我需要将数据放入表变量中,以便进行测试。
DECLARE @ServiceA TABLE (
StartDate DATE,
EndDate DATE,
Price INT);
INSERT INTO @ServiceA VALUES ('2013-01-01', '2013-04-16', 30);
INSERT INTO @ServiceA VALUES ('2013-04-17', '2013-09-20', 33);
INSERT INTO @ServiceA VALUES ('2013-09-21', '2013-12-31', 34);
DECLARE @ServiceB TABLE (
StartDate DATE,
EndDate DATE,
Price INT);
INSERT INTO @ServiceB VALUES ('2013-01-01', '2013-06-30', 47);
INSERT INTO @ServiceB VALUES ('2013-07-01', '2013-12-31', 49);
DECLARE @ServiceC TABLE (
StartDate DATE,
EndDate DATE,
Price INT);
INSERT INTO @ServiceC VALUES ('2013-01-01', '2013-03-03', 96);
INSERT INTO @ServiceC VALUES ('2013-03-04', '2013-12-31', 101);
现在,我可以编写一个可怕的查询,以您想要的方式将数据拉回:
WITH DistinctDates AS (
SELECT
StartDate,
EndDate
FROM
@ServiceA
UNION
SELECT
StartDate,
EndDate
FROM
@ServiceB
UNION
SELECT
StartDate,
EndDate
FROM
@ServiceC),
OrderedDates AS (
SELECT
ROW_NUMBER() OVER (PARTITION BY StartDate ORDER BY EndDate) AS StartNumber,
ROW_NUMBER() OVER (PARTITION BY EndDate ORDER BY StartDate DESC) AS EndNumber,
*
FROM
DistinctDates),
FixOverlaps AS (
SELECT
CASE WHEN o2.StartNumber IS NULL THEN o1.StartDate ELSE DATEADD(DAY, 1, o2.EndDate) END AS StartDate,
CASE WHEN o3.EndNumber IS NULL THEN o1.EndDate ELSE DATEADD(DAY, -1, o3.StartDate) END AS EndDate
FROM
OrderedDates o1
LEFT JOIN OrderedDates o2 ON o2.StartDate = o1.StartDate AND o2.StartNumber = o1.StartNumber - 1
LEFT JOIN OrderedDates o3 ON o3.EndDate = o1.EndDate AND o3.EndNumber = o1.EndNumber - 1),
MergeDates AS (
SELECT
StartDate,
EndDate,
ROW_NUMBER() OVER (PARTITION BY StartDate ORDER BY EndDate) AS MergeNumber
FROM
FixOverlaps)
SELECT
md.StartDate,
md.EndDate,
a.Price,
b.Price,
c.Price
FROM
MergeDates md
LEFT JOIN @ServiceA a ON a.StartDate <= md.EndDate AND a.EndDate >= md.StartDate
LEFT JOIN @ServiceB b ON b.StartDate <= md.EndDate AND b.EndDate >= md.StartDate
LEFT JOIN @ServiceC c ON c.StartDate <= md.EndDate AND c.EndDate >= md.StartDate
WHERE
md.MergeNumber = 1;
......结果是:
StartDate EndDate PriceA PriceB PriceC
2013-01-01 2013-03-03 30 47 96
2013-03-04 2013-04-16 30 47 101
2013-04-17 2013-06-30 33 47 101
2013-07-01 2013-09-20 33 49 101
2013-09-21 2013-12-31 34 49 101