一张表有股票的股票名称,价值和生效日期,并且不会有任何假期/周末的条目。如果我通过包含假日/周末的日期范围,我想返回之前的日期记录。
E.G。
表名:股票
ID Name Value EffectiveDate
1 IBM 200.0000 2015-12-31 00:00:00.000
2 IBM 201.4500 2016-01-04 00:00:00.000
3 IBM 201.0000 2016-01-05 00:00:00.000
4 IBM 202.0000 2016-01-06 00:00:00.000
SELECT Name, Value, EffectiveDate FROM Stock WHERE Name = 'IBM' AND EffectiveDate >= '20151231' AND EffectiveDate <= '20160105'
以上查询返回前3条记录,但我想返回以下结果:
Name Value EffectiveDate ActualDate
IBM 200.0000 2015-12-31 2015-12-31
IBM 200.0000 2015-12-31 2016-01-01
IBM 200.0000 2015-12-31 2016-01-02
IBM 200.0000 2015-12-31 2016-01-03
IBM 201.4500 2016-01-04 2015-01-04
IBM 201.0000 2016-01-05 2015-01-05
01/01/2016至03/01/2016是假期/周末。如果我通过假期/周末日期,我有一个返回上一个日期的函数。任何人都可以帮助在SQL Server中编写查询来实现上述目标吗?
答案 0 :(得分:2)
DECLARE @table TABLE (
id int,
name varchar(20),
value decimal(10, 4),
EffectiveDate datetime
)
INSERT INTO @table
VALUES (1, 'IBM', 200.0000, '2015-12-31 00:00:00.000')
, (2, 'IBM', 201.4500, '2016-01-04 00:00:00.000')
, (3, 'IBM', 201.0000, '2016-01-05 00:00:00.000')
, (4, 'IBM', 202.0000, '2016-01-06 00:00:00.000')
DECLARE @MinDate datetime = '20151231',
@MaxDate datetime = '20160105';
WITH Dates AS (
SELECT @MinDate AS ActualDate
UNION ALL
SELECT DATEADD(day, 1, ActualDate)
FROM Dates
WHERE ActualDate < @MaxDate
)
SELECT [Table].name
,[Table].value
,[Table].EffectiveDate
,[Dates].ActualDate
FROM Dates
CROSS APPLY (
SELECT MAX(EffectiveDate) AS LastEffectiveDate
FROM @table AS [Table]
WHERE [Table].EffectiveDate <= Dates.ActualDate
) AS CA1
INNER JOIN @table AS [Table]
ON [Table].EffectiveDate = CA1.LastEffectiveDate
答案 1 :(得分:0)
如果ActualDate
是周末,则以下代码将返回前一日期所需的EffectiveDate
,但要包含银行假期的逻辑,您需要在表格中定义这些,然后添加更多逻辑如下。
SELECT Name, Value, EffectiveDate,
CASE WHEN datename(dw,EffectiveDate) = 'Saturday'
THEN DATEADD(DAY, -1, EffectiveDate)
WHEN datename(dw,EffectiveDate) = 'Sunday'
THEN DATEADD(DAY, -2, EffectiveDate)
END AS ActualDate
FROM Stock
WHERE Name = 'IBM'
AND EffectiveDate BETWEEN '20151231' AND '20160105'
答案 2 :(得分:0)
这可能不是一个完美的解决方案,但这可以解决问题。
DECLARE @table TABLE (
id int,
name varchar(20),
value decimal(10, 4),
EffectiveDate datetime
)
INSERT INTO @table
VALUES (1, 'IBM', 200.0000, '2015-12-31 00:00:00.000')
, (2, 'IBM', 201.4500, '2016-01-04 00:00:00.000')
, (3, 'IBM', 201.0000, '2016-01-05 00:00:00.000')
, (4, 'IBM', 202.0000, '2016-01-06 00:00:00.000')
DECLARE @MinDate datetime = '20151231',
@MaxDate datetime = '20160105';
SELECT
id,
(CASE
WHEN Data.Value IS NULL THEN (SELECT TOP (1)
value
FROM @table AS T1
WHERE T1.EffectiveDate < Data.FinalDate
ORDER BY FinalDate DESC)
ELSE Data.value
END),
FinalDate
FROM (SELECT
id,
name,
value,
(CASE
WHEN EffectiveDate IS NULL THEN Date
ELSE EffectiveDate
END) AS FinalDate
FROM @table T
FULL OUTER JOIN (SELECT TOP (DATEDIFF(DAY, @MinDate, @MaxDate) + 1)
Date = DATEADD(DAY, ROW_NUMBER() OVER (ORDER BY a.object_id) - 1, @MinDate)
FROM sys.all_objects a
CROSS JOIN sys.all_objects b) H
ON T.EffectiveDate = H.Date) Data
ORDER BY finaldate