将日期范围列转换为月份

Convert Dates range column into months

我有 table 呼叫学生,它有三列 ID、DateFrom、DateTo 现在我想将两个日期列范围 Datefrom 和 Dateto 转换为一列月份作为输出。

table结构如下。日期格式 (yyyy-mm-dd)

ID  DateFrom    DateTo
123 2019-12-03  2020-02-03
456 2020-02-03  2020-02-21

输出结构

ID  Months
123 2019-12
123 2020-01
123 2020-02
456 2020-02

假设您 table 被称为“dataval” 试试这个

;WITH minmax AS (
     SELECT Min(Eomonth(datefrom)) AS MinDate, 
            Max(Eomonth(dateto))   AS MaxDate 
     FROM   dataval), 
 months (date) AS (
     SELECT mindate 
     FROM   minmax 
     UNION ALL 
     SELECT Dateadd(month, 1, date) 
     FROM   months 
     WHERE  Dateadd(month, 1, date) <= (SELECT maxdate FROM minmax)) 
 SELECT ID, FORMAT (date, 'yyyy-MM') Months 
 FROM   dataval 
 INNER JOIN months 
    ON months.date BETWEEN Eomonth(dataval.datefrom) AND Eomonth(dataval.dateto) 

fiddle here

最简单的方法是使用辅助日历 table - 这将在两个 table 之间进行简单连接:

select distinct a.id, convert(char(7), b.[Date], 120) as month
from yourTable as a
join Calendar as b
    on a.DateFrom <= b.[Date]
    and a.DateTo >= b.[Date]
;

如果您没有日历 table,您可能需要考虑添加一个。

如果您不能(或不想)添加日历 table,您可以使用数字(理货)获得相同的结果 table。
如果您没有计数 table,您可以使用常见的 table 表达式即时生成计数。

在这种情况下,您的 SQL 会是这样的:

WITH N10 AS
(
    SELECT n
    FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9))V(n)
), Tally AS
(
    SELECT TOP (SELECT MAX(DATEDIFF(MONTH, DateFrom, DateTo)) + 1 FROM yourTable) ROW_NUMBER() OVER(ORDER BY @@SPID) -1 As n
    FROM N10 As Ten
    CROSS JOIN N10 As Hundred
    --CROSS JOIN N10 As Thousand
)

SELECT [ID], CONVERT(char(7), Months, 120) As Months
FROM yourTable
CROSS APPLY 
(
    SELECT N, DATEADD(MONTH, N, [DateFrom]) As Months
    FROM Tally 
) X
WHERE Months <= EOMONTH([DateTo])
ORDER BY Id, Months