【问题标题】:How to get a list of months and year between two dates in SQL Server如何在 SQL Server 中获取两个日期之间的月份和年份列表
【发布时间】:2023-03-22 21:58:01
【问题描述】:

我必须获取日期之间的月份和年份列表。目前它只返回具有相关数据的日期的月份和年份。

例如,我的日期介于:'8'+'/1'+'/'+'2015' and DATEADD(mm, 15, '8'+'/1'+'/'+'2016'

它只打印出:May2016, June2016, July2016, Auguest2016, September2016

我希望它打印出其间的所有月份和年份。这是我的 sql 查询:

select d.id_base as case_id, 
    c.C_LAST_ACTION AS Docketed,
    c.C_CASE_TYPE AS caseType,
    ct.C_NAME As caseName, 
    ct.C_DESCRIPTION AS caseNameDescription,
   case when d.c_mod_decision_id is not null then '' else  DATENAME(mm, d.c_issue_date) + DATENAME(yyyy, d.c_issue_date)  end as display
from t_case_decision d JOIN T_CASE_INPUT c on c.id = d.id_base JOIN T_CASE_TYPE ct on C_CASE_TYPE = ct.id 
where cast(d.c_issue_date AS date) BETWEEN '8'+'/1'+'/'+'2015' and DATEADD(mm, 15, '8'+'/1'+'/'+'2016') 

【问题讨论】:

  • '8'+'/1'+'/'+'2015',嗯?这真的很奇怪。您的语法是如此清晰的 SQL Server,以至于我修改了问题以反映这一点。
  • @GordonLinoff 目前我正在尝试获取从该月开始到 15 个月的所有数据。即使月份没有数据,我也需要打印出所有月份和年份。
  • @GordonLinoff 不确定这对您是否有意义。
  • 呃,你真的需要连接月份、日期和年份的值吗?
  • @L.Herrera 是的,因为我使用相同的查询在 ireport 中构建报告,显示月+年

标签: sql-server date


【解决方案1】:

首先,创建一个numbers table

CREATE TABLE Numbers(N INT)

insert into Numbers(N)
select top 1000000 row_number() over(order by t1.number) as N
from   master..spt_values t1 
       cross join master..spt_values t2

然后使用DATEADD 列出所需值之间的日期,像这样

declare @iniDate as date     
set @iniDate='20150801'  

select dateadd(MONTH,N,@iniDate) dates
from Numbers 
where N<15 order by N

这些返回日期从 @iniDate 到 15 个月后

编辑:试试这个,我现在没有 sql

select datename(mm, dateadd(MONTH,N,@iniDate))+datename(yyyy ,dateadd(MONTH,N,@iniDate)) display
from ( select top 15row_number() over(order by t1.number) as N
from   master..spt_values t1 
       cross join master..spt_values t2) numbers right join (

    select d.id_base as case_id, 
        c.C_LAST_ACTION AS Docketed,
        c.C_CASE_TYPE AS caseType,
        ct.C_NAME As caseName, 
        ct.C_DESCRIPTION AS caseNameDescription,
       case when d.c_mod_decision_id is not null then '' else  DATENAME(mm, d.c_issue_date) + DATENAME(yyyy, d.c_issue_date)  end as display
    from t_case_decision d JOIN T_CASE_INPUT c on c.id = d.id_base JOIN T_CASE_TYPE ct on C_CASE_TYPE = ct.id 
    where cast(d.c_issue_date AS date) BETWEEN '8'+'/1'+'/'+'2015' and DATEADD(mm, 15, '8'+'/1'+'/'+'2016') 
    sql-server
    ) qq
on datename(mm, dateadd(MONTH,N,@iniDate))+datename(yyyy ,dateadd(MONTH,N,@iniDate)) = qq.display

where N<15 order by N

【讨论】:

  • 这对我不起作用我正在尝试使用相同的查询在 ireport 中构建报告我尝试使用 DATEADD(mm, 15, '8'+'/1'+'/' +'2016') 附近的语法不正确
  • @ReazurRahman 不确定您的日期字符串,但试试这个,因为我尝试显示 DATEADD(month, N, '8'+'/1'+'/'+'2016') 加入数字表和 WHERE numbers.N&lt;15
  • @ReazurRahman 我刚刚又读了一遍,你说It only prints out: May2016, June2016, July2016, Auguest2016, September2016 I want it to print out all of the months and year in between. Here is my sql queries: 你是否只有这些日期的数据?
  • 是的,数据仅适用于那些月份,但我希望能够打印出所有月份,无论它有数据还是根本没有数据。
  • @ReazurRahman 查看我的编辑,也许它不会编译,只需使用它即可。告诉我进展如何
【解决方案2】:

如果我了解您要完成的工作,递归 CTE 可能会有所帮助。这是您可以做什么的快速示例。 CTE 将扩展为日期列表,然后您可以将其用作查询的基础。

TargetData CTE 的内容可能需要调整,因为我没有完整的数据结构图。

DECLARE @startDate DATE = '1/1/2015';
DECLARE @endDate DATE = '7/31/2016';

-- Recursive CTE to generate a list of months within the date range:
WITH Months AS (
    SELECT CONVERT(DATE, DATEADD(D, -(DAY(@startDate)) + 1, @startDate)) [MonthDate]

    UNION ALL

    SELECT DATEADD(M, 1, MonthDate)
    FROM Months
    WHERE MonthDate <= DATEADD(M, -1, @endDate)
),
TargetData AS (
    -- This is a slightly modified version of the original query:
    select
        d.id_base as case_id, 
        c.C_LAST_ACTION AS Docketed,
        c.C_CASE_TYPE AS caseType,
        ct.C_NAME As caseName, 
        ct.C_DESCRIPTION AS caseNameDescription,
        case when d.c_mod_decision_id is not null then '' else  DATENAME(mm, d.c_issue_date) + DATENAME(yyyy, d.c_issue_date)  end as display,
        -- Return the "MonthDate" so that it can be left joined to the Months table:
        DATEADD(D, -(DAY(d.c_issue_date)) + 1, d.c_issue_date) [MonthDate]
    from t_case_decision d JOIN T_CASE_INPUT c on c.id = d.id_base JOIN T_CASE_TYPE ct on C_CASE_TYPE = ct.id 
    where cast(d.c_issue_date AS date) BETWEEN @startDate AND @endDate
)
SELECT
    m.MonthDate,
    DATENAME(mm, m.MonthDate) + DATENAME(yyyy, m.MonthDate),
    td.*
FROM Months m
    LEFT JOIN TargetData td ON td.MonthDate = m.MonthDate;

【讨论】:

  • 请注意,这只适用于 SQL Server 2005 及更高版本。
  • 有没有办法在不创建表格的情况下做到这一点。
  • @ReazurRahman,我更新了示例以合并您的原始查询而不是临时表。原始示例中的临时表旨在使其更通用,但可能有点混乱。
  • 嘿,如果我想回到 15 个月而不是前进,我会怎么做。我试图做的月份日期大于或等于对我不起作用
  • @ReazurRahman,很抱歉,但我不确定我是否理解你的问题。要调整查询返回的数据范围,您应该能够调整@startDate@endDate 变量。这有帮助吗?
【解决方案3】:

您需要连接表之间的主键,我还没有看到使用该语法的 between 语句。所以我建议尝试以下方法:

SELECT d.id_base as case_id, c.C_LAST_ACTION AS 'Docketed',c.C_CASE_TYPE AScaseType,ct.C_NAME As 'caseName', ct.C_DESCRIPTION AS 'caseNameDescription'
,CASE 
WHEN d.c_mod_decision_id is not null THEN '' AS 'null_val'
ELSE  CONCAT(YEAR(d.c_issue_dateDATENAME), MONTH(d.c_issue_date))
END AS 'display'

FROM t_case_decision d INNER JOIN T_CASE_INPUT c on c.id = d.id_base 
INNER JOIN T_CASE_TYPE ct on c.id = ct.id 

WHERE CONVERT(DATE,d.c_issue_date) BETWEEN '08/01/2015' 
AND '08/01/2016';

我希望这对您有所帮助或指出正确的方向:)

【讨论】:

  • 这不起作用。就像我说的那样,我需要从 2015 年 8 月 1 日开始的 15 个月的数据,并且我需要这几个月之间的所有月份和年份。你刚才所做的给了我和以前一样的结果。
  • 我认为您可以根据我的示例进行调整以满足您的需求....您需要添加一个案例语句,例如:case WHEN MONTH(d.c_issue_date) = 1 THEN 'January' ...每个月都这样做,然后在您的 select 语句中添加 YEAR(d.c_issue_date),在 select 语句中添加您需要的其余数据,WHERE d.c_issue_date BETWEEN '08/01/2015' AND DATEADD( MONTH, 15, '08/01/2015') GROUP BY YEAR(d.c_issue_date), MONTH(d.c_issue_date) etc..., ORDER BY d.c_issue_date DESC etc...;现在接受挑战和编码,不能为你做所有的工作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-07
  • 2020-08-13
  • 2011-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多