【问题标题】:SQL date interval every 6 monthsSQL 日期间隔每 6 个月
【发布时间】:2021-07-21 00:35:25
【问题描述】:

My SQL Server 2014 表包含一个名为 CreatedOndatetime 列。

每天我都需要确定在该日期创建的公司恰好是 6 个月前或 6 个月前的倍数(即存储日期时间后 6 个月、12 个月后、18 个月后等)。我可以编写查询的其余部分,但无法弄清楚如何识别与日期列表匹配的行(即 2020 年 10 月 27 日、2020 年 4 月 27 日、2019 年 10 月 27 日、2019 年 4 月 27 日、2018 年 10 月 27 日、2018 年 4 月 27 日,等)。

这是获取恰好在 6 个月前创建的公司的查询。如何调整查询以包含额外的 6 个月间隔?

select * 
from work 
where DATEPART(d, CreatedOn) = DATEPART(d, DATEADD(m, -6, getdate()))
  and DATEPART(m, CreatedOn) = DATEPART(m, DATEADD(m, -6, getdate()))
  and DATEPART(yyyy, CreatedOn) = DATEPART(yyyy, DATEADD(m, -6, getdate()))

样本数据

Name          CreatedOn
-------------------------------------
Company A     2020-10-27 13:49:15.597
Company B     2021-04-27 15:25:09.720
Company C     2021-03-16 15:50:01.443
Company D     2018-04-27 21:58:18.903

Data Table

我希望 A 公司和 D 公司出现在我的结果集中

【问题讨论】:

  • 什么行?样本数据和期望的结果会有所帮助。
  • 为此您需要一个日历或计数表。它可以作为查询的一部分即时生成。此代码是特定于 DBMS 的。你的 DBMS 是什么?
  • @Serg - 运行 MS SQL 2014

标签: sql sql-server datetime dateadd


【解决方案1】:

我认为如果您可以合并一个像 Communication 这样的新表格会更好,您可以在其中为您的公司在需要发送电子邮件时生成时间表。通过比较该表中的日期,您可以向他们发送邮件。这将是一种更简洁的方法,您将能够验证公司何时真正收到电子邮件。您可以向该表 IsEmailSend 添加更多列,以过滤掉数据并用于报告目的。

CompanyId | EmailSchedule | IsEmailSend
1 | 2020-10-27 | 1
1 | 2021-04-27 | 0
...

您必须根据公司创建日期预先填充和管理此表数据。您可以通过一些将在某个时间间隔触发的存储过程来执行此操作。

【讨论】:

    【解决方案2】:

    我会像 db<>fiddle sample 那样将日期时间范围分隔在单独的变量中:

    查询:

    -- How can I select the first day of a month in SQL?
    -- Source: https://stackoverflow.com/a/1520803/12511801
    
    -- First day of the date (6 months back): 
    DECLARE @date_start_range DATE = CAST(DATEADD(month, DATEDIFF(month, 0, DATEADD(MONTH, -6, GETDATE())), 0) AS DATE);
    
    -- First day of the current month: 
    DECLARE @date_end_range DATE = CAST(DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0) AS DATE);
    
    -- Query results where CreatedOn is between current date and 6 months back: 
    SELECT W.* 
    FROM work AS W
    WHERE CAST(W.CreatedOn AS DATE) BETWEEN @date_start_range AND @date_end_range;
    GO
    

    结果:

    姓名 |创建于 :-------- | :------------------------ A公司| 2020-10-27 13:49:15.597 C公司| 2021-03-16 15:50:01.443

    【讨论】:

      【解决方案3】:

      这是DATEDIFF 的工作。

      试试这样的。

      WITH Dates AS (
      SELECT DATEDIFF(month, CreatedOn, GETDATE()) monthsago,
             Name
        FROM sample 
      )
      SELECT * 
        FROM Dates
       WHERE monthsago % 6 = 0
         AND monthsago > 0
      

      请参阅fiddle

      您仍然需要跟踪您发送的消息,以避免错误地向您的客户发送垃圾邮件。

      【讨论】:

      • 但我认为 datediff 将在整个月份返回相同的值,然后将电子邮件发送给用户。我认为这不是预期的。
      • 是的 - 以上不是我需要的特定日期。
      【解决方案4】:

      我想多了。我并不真正关心年份和月份中的日期将始终是当前日期(在午夜之前运行),我只需要获取当前月份和 6 个月前的月份。

      从工作中选择 * 其中 DATEPART(d, CreatedOn) = DATEPART(d, getdate()) AND (DATEPART(m, CreatedOn) = DATEPART(m, DATEADD(m, -6, getdate())) 或 DATEPART(m, CreatedOn) = DATEPART(m, getdate()))

      感谢大家的帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-12
        • 2012-10-28
        • 2019-12-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-02
        • 1970-01-01
        • 2021-04-04
        相关资源
        最近更新 更多