假设我有一个表格,其中价格和日期为列,如:
Price Date
3.20000000 2018-01-14
3.20000000 2018-01-18
3.20000000 2018-01-19
4.00000000 2018-02-10
4.00000000 2018-02-11
4.00000000 2018-02-12
5.10000000 2018-02-16
3.20000000 2018-03-11
4.00000000 2018-03-15
我希望每次出现新价格时都获得第一个日期,并希望在同一日期列中获得该价格的最后日期(加上一天)。 请注意,价格可以上下波动,同一价格在整个表格中可能出现多次。因此上表的结果应为:
Price Date
3.20000000 2018-01-14
3.20000000 2018-01-20 -- 19 + 1
4.00000000 2018-02-10
4.00000000 2018-02-13 -- 12 + 1
5.10000000 2018-02-16
5.10000000 2018-02-17 -- 16 + 1
3.20000000 2018-03-11
3.20000000 2018-03-12 -- 11 + 1
4.00000000 2018-03-15
4.00000000 2018-03-16 -- 15 + 1
我希望使用自联接,是否可以在没有row_number
函数的情况下进行自联接?
答案 0 :(得分:1)
这是一个变体。您可以对其进行修改以适合您的需求。
DECLARE @DataSource TABLE
(
[Price] SMALLMONEY
,[Date] DATE
);
INSERT INTO @DataSource ([Price], [Date])
VALUES ('3.20000000', '2018-01-14')
,('3.20000000', '2018-01-18')
,('3.20000000', '2018-01-19')
,('4.00000000', '2018-02-10')
,('4.00000000', '2018-02-11')
,('4.00000000', '2018-02-12')
,('5.10000000', '2018-02-16')
,('3.20000000', '2018-03-11')
,('4.00000000', '2018-03-15');
-- we need to order the data, if you do not want to use ROW_NUMBER(), use another way to order it (for exmaple record ID of each row using IDENTITY column)
WITH DataSourceOrdered AS
(
SELECT ROW_NUMBER() OVER(ORDER BY [Date]) AS [RowID]
,[Price]
,[Date]
FROM @DataSource
), RecordsWhenPriceChanged AS
(
-- records when price has changed
SELECT DS1.[Price]
,DS1.[Date]
,DS1.[RowID]
FROM DataSourceOrdered DS1
INNER JOIN DataSourceOrdered DS2
ON DS1.[RowID] -1 = DS2.[RowID]
AND DS1.[Price] <> DS2.[Price]
UNION ALL
-- the initial record
SELECT [Price]
,[Date]
,[RowID]
FROM DataSourceOrdered
WHERE [RowID] = 1
)
-- getting current records
SELECT [Price]
,[Date]
,[RowID]
FROM RecordsWhenPriceChanged
UNION ALL
-- getting previous records + 1 day for each
SELECT DS1.[Price]
,DATEADD(DAY, 1, DS1.[Date])
,DS1.[RowID]
FROM DataSourceOrdered DS1
INNER JOIN RecordsWhenPriceChanged DS2
ON DS1.[RowID] + 1 = DS2.[RowID]
-- getting the last record
UNION ALL
SELECT *
FROM
(
SELECT TOP 1 [Price]
,DATEADD(DAY, 1,[Date]) AS [Date]
,[RowID]
FROM RecordsWhenPriceChanged
ORDER BY [Date] DESC
) DS
ORDER BY [Date];
答案 1 :(得分:1)
正如我在评论中所写,这是一个典型的空白和孤岛问题,解决此问题的简单方法是两次使用row_number
。
首先,创建并填充示例表(请在您将来的问题中为我们保存此步骤):
DECLARE @T AS TABLE
(
Price decimal(15,5),
[Date] Date
)
INSERT INTO @T (Price, [Date]) VALUES
(3.20000000, '2018-01-14'),
(3.20000000, '2018-01-18'),
(3.20000000, '2018-01-19'),
(4.00000000, '2018-02-10'),
(4.00000000, '2018-02-11'),
(4.00000000, '2018-02-12'),
(5.10000000, '2018-02-16'),
(3.20000000, '2018-03-11'),
(4.00000000, '2018-03-15')
现在,使用公共表格表达式标记岛:
;WITH CTE AS
(
SELECT Price,
[Date],
ROW_NUMBER() OVER(ORDER BY [Date]) -
ROW_NUMBER() OVER(PARTITION BY Price ORDER BY [Date]) As Island
FROM @T
)
然后使用联合查询进行查询-一个使用min(date) over(partition by island)
,第二个使用max(dateadd(day, 1, date)) over(partition by island)
,按日期对结果进行排序:
SELECT Price, MIN(Date) OVER (PARTITION BY Island) As [Date]
FROM CTE
UNION
SELECT Price, DATEADD(DAY, 1, MAX(Date) OVER (PARTITION BY Island))
FROM CTE
ORDER BY Date
结果:
Price Date
3,20000 14.01.2018
3,20000 20.01.2018
4,00000 10.02.2018
4,00000 13.02.2018
5,10000 16.02.2018
5,10000 17.02.2018
3,20000 11.03.2018
3,20000 12.03.2018
4,00000 15.03.2018
4,00000 16.03.2018
答案 2 :(得分:0)
您可以尝试不使用row_number
的此解决方案。
DECLARE @MyTable TABLE ([Price] DECIMAL(18,8), [Date] DATE);
INSERT INTO @MyTable ([Price], [Date])VALUES
('3.20000000', '2018-01-14'),
('3.20000000', '2018-01-18'),
('3.20000000', '2018-01-19'),
('4.00000000', '2018-02-10'),
('4.00000000', '2018-02-11'),
('4.00000000', '2018-02-12'),
('5.10000000', '2018-02-16'),
('3.20000000', '2018-03-11'),
('4.00000000', '2018-03-15')
;WITH CTE AS
(
SELECT * FROM @MyTable
UNION ALL
SELECT Price, DATEADD(DAY,1,[Date]) FROM @MyTable
)
, CTE2 AS (
SELECT T1.Price, MIN(T1.[Date]) MinDate, MAX(T1.[Date]) MaxDate
FROM CTE T1
OUTER APPLY( SELECT COUNT(DISTINCT Price) DCNT, MIN(Date) [Date] FROM CTE T2 WHERE T2.Date >= T1.Date ) TA1
GROUP BY T1.Price, TA1.DCNT
)
SELECT Price, [Date] FROM CTE2 UNPIVOT ( [Date] FOR Col IN (MinDate, MaxDate)) UNPVT
ORDER BY [Date]
结果:
Price Date
--------------------------------------- ----------
3.20000000 2018-01-14
3.20000000 2018-01-20
4.00000000 2018-02-10
4.00000000 2018-02-13
5.10000000 2018-02-16
5.10000000 2018-02-17
3.20000000 2018-03-11
3.20000000 2018-03-12
4.00000000 2018-03-15
4.00000000 2018-03-16