【问题标题】:SQL Server: Return all rows of a table which date field satisfies some date conditionsSQL Server:返回日期字段满足某些日期条件的表的所有行
【发布时间】:2017-07-28 09:46:18
【问题描述】:

我有一张有很多员工的表,比如说“员工”表。此表有一个日期列等。假设此列名为“InjuryDate”。

我想选择所有满足以下条件的员工:

  1. InjuryDate 在当前月份内,例如,如果当前月份是 7 月,我希望所有员工:InjuryDate >= 01/07/2017 和 InjuryDate
  2. InjuryDate 介于上个月的第 20 天和当月的第一天之间。例如,如果当前月份是 7 月,我希望所有员工满足:InjuryDate >= 20/06/2017 和 InjuryDate

所以考虑到here所说的(考虑到SQL Server可以在列上使用索引,如果合适的话),我做了以下查询:

DECLARE @today datetime = getdate()

DECLARE @Day int  = 20
DECLARE @Month int  = MONTH(dateadd(month, -1, @today))
DECLARE @Year int = YEAR(dateadd(month, -1, @today))
DECLARE @EarlyDate datetime = cast(cast(@Year*10000 + @Month*100 + @Day as varchar(255)) as date)

SELECT *
FROM   Employees
WHERE  (
         -- Condition 1
         InjuryDate >= cast(@today - day(@today) + 1 as date) 
            AND
         InjuryDate < dateadd(month, 1, cast(@today - day(@today) + 1 as date) )
       )
         OR
       (    
         -- Condition 2
         InjuryDate >= @EarlyDate
            AND 
         InjuryDate < cast(@today - day(@today) + 1 as date) 
       )

是否正确,或者有其他更好的方法吗?

我使用的是 SQL Server 2008。

【问题讨论】:

    标签: sql-server sql-server-2008 datetime sql-server-2008-r2 getdate


    【解决方案1】:

    试试这个:

    DECLARE @today date = getdate();
    
    DECLARE @todayDay int  = datepart(day, @today);
    DECLARE @earlyDate date = dateadd(day, 19, DATEADD(month, DATEDIFF(month, 0, @today) - 1, 0));
    DECLARE @nextMonthFirstDayDate date = DATEADD(month, DATEDIFF(month, 0, @today) + 1, 0);
    
    SELECT *
    FROM (
            VALUES  (1, '2017-06-19'),
                    (2, '2017-06-20'),
                    (3, '2017-07-19'),
                    (4, '2017-07-31'),
                    (5, '2017-08-01')
         ) AS Employees(Id,InjuryDate)
    WHERE  InjuryDate >= @earlyDate AND InjuryDate < @nextMonthFirstDayDate;
    

    输出:

    Id          InjuryDate
    ----------- ----------
    2           2017-06-20
    3           2017-07-19
    4           2017-07-31
    

    【讨论】:

    • @today 是 2017 年 7 月 31 日时似乎失败了,它不会在 20 日开始。
    【解决方案2】:

    基本上,您需要获取从上个月 20 日到当月最后一天的所有记录。您确实需要 OR。

    DECLARE @end_range DATE= DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0)),
        @start_rage DATE= DATEADD(m, DATEDIFF(m, 0, DATEADD(m, DATEDIFF(m, 0, GETDATE()), -1)), 19)  
    
    SELECT *
    FROM   Employees
    WHERE InjuryDate BETWEEN @start_range AND @end_rage
    

    【讨论】:

    • 为什么在@start_range 中使用秒?有必要吗?还是只考虑日期并丢弃时间就足够了?同样在您的回答中,您有开关 start_range 和 end_range,请更正。
    • 另外我的 InjuryDate 字段只是一个日期列,我的意思是,它没有时间,时间设置为 00:00:00.0。在同一张表中,我还有另一列“InjuryTime”,其中仅包含时间(无日期)。
    • 尽管我的列 InjuryDate 字段仅包含日期,但我认为您的解决方案还可以。请你确认一下好吗?
    • @Rodri 你必须选择最佳答案并接受它:stackoverflow.com/help/someone-answers
    • 修复了结束和开始范围并使用 DATE 而不是 DATETIME
    【解决方案3】:

    。删除我的答案,因为有人觉得这是偷窃

    【讨论】:

    • @RuslanK。我已经删除了我的答案,因为你觉得它是偷窃,这不是偷窃,它只是以其他方式表示
    猜你喜欢
    • 2021-06-08
    • 1970-01-01
    • 1970-01-01
    • 2019-04-30
    • 1970-01-01
    • 1970-01-01
    • 2012-03-29
    • 1970-01-01
    相关资源
    最近更新 更多