【问题标题】:Get previous month date values from data stored within SQL Server table从存储在 SQL Server 表中的数据中获取上个月的日期值
【发布时间】:2019-07-02 03:34:12
【问题描述】:

我在 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 值,但这些月的值应该是我们在较早的月份是八月的值,在此示例中为 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

你觉得这里不用光标也能做到吗?

【问题讨论】:

  • 您使用的是什么版本的 SQL Server?顺便说一句,您在提出问题方面做得很好。
  • 错字? 1 2018-12-13 2018-12-10 15 时光倒流,直到 1 月中旬才离开。
  • @Brian,我们有 SQLServer 13。
  • @MatBailie,是的。谢谢你发现那个错字。让我现在解决这个问题。再次感谢您。

标签: sql sql-server database tsql


【解决方案1】:

Alexander Volok 的回答是可靠的,所以我不会涉及太多额外的代码。但我想我会解释其中的原因。本质上,您需要做的是创建一个包含您想要返回的所有日期和主键的骨架日期表。我猜你的真实数据中有不止一个 id 值,所以可能是这样的(你是否选择坚持它取决于你)

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

    primary key (id, _year, _month)
)

如果需要,您可以更加精确,方法是仅包括介于 StartDateid 的最小值和最大值之间的日期,但这是我留给您的练习。

从那里开始,只需在骨架表中填写您关心的值即可。您可以通过多种方式做到这一点;通过加入、交叉应用或相关子查询(正如 Alexander Volok 使用的那样)。

【讨论】:

  • 是的。我在真实数据中有许多其他的 Id 值,我几乎采用了 Alexander Volok 展示的方法,并在它周围添加了我的其他东西。它确实有帮助。非常感谢 Xedni 对此提供的帮助。
【解决方案2】:
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

【讨论】:

  • 这是完美的。我认为这是我的工作。我可以采用这种方法并进一步修改它以添加我正在寻找的其他东西。非常感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-19
  • 2018-06-21
相关资源
最近更新 更多