【问题标题】:SQL check if date is N days back from last monthSQL检查日期是否是上个月的N天
【发布时间】:2016-12-11 19:29:05
【问题描述】:

我需要根据 dateIssued 检查发票的编辑(在表格中可以说发票)。

(SQL Server 2008 R2)

这个想法是,上个月的发票数据可以在当月的第 N 天之前更改。之后,只能更改当月发票。发票绝对不能在 2 个月后更改,以此类推。

示例。假设 N = 20 天

这意味着我可以在 12 月 20 日之前更改 11 月的发票。在 12 月 21 日,我只能更改 12 月的发票。

我希望我的描述性足够 :(

SELECT invoiceNo, dateIssued FROM Invoices;

invoiceNo dateIssued
001       2016-10-30 00:00:00.000
002       2016-12-01 00:00:00.000
003       2016-11-03 00:00:00.000
004       2016-11-24 00:00:00.000
005       2016-09-09 00:00:00.000

我无法构建一个优雅的算法来根据系统的日期从表格中选择正确的编辑发票。

感谢

【问题讨论】:

  • 您希望查询做什么?样本数据期望的结果会很有帮助。
  • 从表格中简单选择,根据系统日期和上述要求的过滤器检索可以更改的发票

标签: sql sql-server date


【解决方案1】:

如果您想获得今天可以修改的发票,那么可以这样:

select i.*
from invoices i
where year(dateissued) * 12 + month(dateissued) = year(getdate()) * 12 + month(getdate()) or
      (day(getdate()) <= @n and
       year(dateissued) * 12 + month(dateissued) = year(getdate()) * 12 + month(getdate()) - 1
      ) ;

使用年 * 12 + 月的时髦表达式只是获取从零开始的月数。方便获取当前和上个月。

【讨论】:

    【解决方案2】:
    DECLARE @Invoices AS TABLE (InvoiceNo INT, dateIssues DATETIME)
    INSERT INTO @Invoices VALUES
    (1,'2016-10-30 00:00:00.000')
    ,(2,'2016-12-01 00:00:00.000')
    ,(3,'2016-11-03 00:00:00.000')
    ,(4,'2016-11-24 00:00:00.000')
    ,(5,'2016-09-09 00:00:00.000')
    
    DECLARE @N INT = 20
    
    SELECT
        *
    FROM
        @Invoices
    WHERE
        dateIssues >=
        CASE WHEN DAY(GETDATE()) < @N
           THEN DATEADD(MONTH,-1,DATEADD(DAY,1 - DAY(GETDATE()),CAST(GETDATE() AS DATE))) --beginning of last month
           ELSE DATEADD(DAY,1 - DAY(GETDATE()),CAST(GETDATE() AS DATE))  --beginning of this month
        END
    

    【讨论】:

    • 看起来这个解决方案也会返回未来几个月的发票,问题暗示这不是意图:“之后,只有当月发票可以更改。” .
    • @3N1GM4 使用过去时 dateIssued 可能不会在未来“开具”发票,这意味着数据集中不存在当前月份之后的发票。但如果是这种情况,我不会看到任何商业原因,如果一个人能够在下个月的 n (20) 天之前更改发票并且当它“最终确定”时,它们将无法更改。未来的发票不会被隐含地允许更改吗?
    • 很公平Matt,我同意你的观点,只是认为值得指出以防PanosPlat 想澄清他们的问题。
    • @3N1GM4 你的评论让我三思而后行。讨论并不是一件坏事,因为它有助于 OP 了解不同解决方案的细微差别,在讨论日期/日期时间时总会有一些细微差别。考虑到 OP 术语,两者都是很好且合理的解决方案,所以我理解评论只是不是反对票,但谁知道这可能来自其他人。干杯
    • 我同意马特,否决票是由于 OP 明确表示“我可以更改 12 月的发票。”在他们的例子中,但我承认这似乎不太可能是他们的真实意图(尽管这是我们正在讨论的不太可能的极端情况)。不幸的是,我现在撤回我的反对票为时已晚,抱歉。
    【解决方案3】:
    DECLARE @LastDayForEditingPreviousMonth INT = 20
    
    -- Return only invoices for the current month, of those for last month if the @LastDayForEditingPreviousMonth day has not been passed
    SELECT *
    FROM invoices
    WHERE (     DATEPART(YEAR,dateissued) = DATEPART(YEAR,GETDATE()) 
            AND DATEPART(MONTH,dateissued) = DATEPART(MONTH,GETDATE())
          ) -- Invoices for this month
    OR (    DATEPART(DAY,GETDATE()) <= @LastDayForEditingPreviousMonth
        AND DATEPART(YEAR,dateissued) = DATEPART(YEAR,GETDATE())
        AND DATEPART(MONTH,dateissued) = DATEPART(MONTH,GETDATE()) - 1
    ) -- Invoices from last month (if eligible)
    

    【讨论】:

    • 如果“下”月的发票提前存在,则无法更改它们。此外,由于无法使用索引,因此列上的日期计算不会像直接比较那样执行。
    • 正如您在回答 Matt 的 cmets 中所讨论的那样,如果未来一个月内有带有 dateIssued 值的发票,则不清楚需要哪种行为,但您显然是对的如果它们可以存在并且在结果中是需要的,我的解决方案将不会返回它们,相反,即使它们不需要,您的解决方案返回它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-01
    • 1970-01-01
    • 2015-08-16
    • 2021-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多