从SQL Server表中存储的数据中获取上个月的日期值

时间:2019-02-07 22:14:46

标签: sql sql-server database tsql

我在SQL Server中的表结构如下所示。

id     startdate     enddate     value
---------------------------------------
1     2019-02-06    2019-02-07    11
1     2019-01-22    2019-02-05    10
1     2019-01-15    2019-01-21    14
1     2018-12-13    2018-01-14    15
1     2018-12-09    2018-12-12    14
1     2018-08-13    2018-12-08    17
1     2018-07-19    2018-08-12    19
1     2018-06-13    2018-07-18    20

现在,我的查询需要显示该月最高开始日期的值。很好,我知道需要做什么,但不能仅从该月的最高日期值开始,如果该开始日期没有值,则从上个月结转值。因此,基本上如果您注意到上述数据,则2018年12月的值之后没有11月,10月,9月等的值,但我想返回该月的MM / YYYY值,但这些月的值应为我们在上找到的值较早的月份,即8月的值,在此示例中为17。请注意,结束日期将始终为新开始日期开始的前一天。可能可以用于回填并结转缺少的月份值吗?

所以我的结果应该如下所示。

id     date         value
----------------------------
1     2019-02        11
1     2019-01        10
1     2018-12        15
1     2018-11        17
1     2018-10        17
1     2018-09        17
1     2018-08        17
1     2018-07        19
1     2018-06        20

您认为无需在此处使用游标就可以做到吗?

2 个答案:

答案 0 :(得分:2)

亚历山大·沃洛克(Alexander Volok)的回答很可靠,因此我不会涉及太多额外的代码。但是我想我会解释原因。本质上,您需要做的是创建一个包含所有要返回的日期和主键的框架日期表。我猜您的真实数据中有多个id值,所以大概是这样(您是否选择保留它取决于您)

create table #skelly
(
    id int,
    _year int,
    _month int

    primary key (id, _year, _month)
)

如果需要的话,可以通过只包含介于每个StartDate的最大id和最大<?xml version="1.0" encoding="utf-8"?> 之间的日期来获得更加精确的信息,但这是我的工作。 >

从那里开始,只需在骨架表中填写您关心的值即可。您可以通过多种方式执行此操作。通过加入,交叉应用或相关子查询(如Alexander Volok使用)。

答案 1 :(得分:1)

DECLARE @start DATE, @end DATE;
SELECT @start = '20180601', @end = GETDATE();

;WITH Months AS 
(

  SELECT EOMONTH(DATEADD(month, n-1, @start)) AS DateValue FROM (
  SELECT TOP (DATEDIFF(MONTH, @start, @end) + 1)   
  n = ROW_NUMBER() OVER (ORDER BY [object_id])
  FROM sys.all_objects
  ) D
)


, InputData AS 
(

SELECT 1  AS id,    '2019-02-06' startdate,    '2019-02-07' as enddate,   11 AS [value] UNION ALL
SELECT 1,     '2019-01-22',    '2019-01-25',    10 UNION ALL
SELECT 1,     '2019-01-15',    '2019-01-17',    14 UNION ALL
SELECT 1,     '2018-12-13',    '2018-12-19',    15 UNION ALL
SELECT 1,     '2018-12-09',    '2018-12-10',    14 UNION ALL
SELECT 1,     '2018-08-13',    '2018-12-08',    17 UNION ALL
SELECT 1,     '2018-07-19',    '2018-07-25',    19 UNION ALL
SELECT 1,     '2018-06-13',    '2018-07-18',    20 
)

SELECT  FORMAT(m.DateValue, 'yyyy-MM') AS [Month]
, (SELECT TOP 1 I.value FROM InputData I WHERE I.startdate < M.DateValue ORDER BY I.startdate DESC ) [Value]
FROM months m
ORDER BY M.DateValue DESC

结果至:

Month   Value
2019-02 11
2019-01 10
2018-12 15
2018-11 17
2018-10 17
2018-09 17
2018-08 17
2018-07 19
2018-06 20