当月末是中周时,如何提取周结束日期和月末

时间:2019-02-18 22:58:59

标签: sql sql-server tsql date

我不确定如何进行此操作或要搜索的内容,但是在这里我尝试解释我要做什么!可能还有多种方法可以解决这个问题。

我正在开发一个“时间卡”项目,在这里我希望提取一周内未填写最短时间的所有时间卡。假设一个正常的星期是40个小时。

我还有第二张表,告诉我所有星期的结束日期。但是在大多数情况下,这是每个星期六,如果月份在周中结束,则该天是一周的结束。因此,一月我们有一个星期的结束日期为1月31日,一个是2月2日。

其中1月31日只需要32小时,而2月2日只需要8小时。

样本数据

Week Ending Date   Minimum Hours
1/26/19             40
1/31/19             32
2/2/19              8
2/9/19              40

时间卡示例

NAME                WeekEnding           HoursWorked
Billy Joe           1/23/19               42
Homer               1/30/19               32
Marge               1/31/19               40
Homer               2/2/19                8

理想情况下,我会按Week_ending日期加入这2个表,但有时人们在时间卡上输入错误的日期。假设他们输入1月30日至31日。因此,我无法为TSQL做一个简单的周末查找。因此,如果我加入上述两个示例,由于荷马在自己的TimeCard中输入了错误的日期,因此第31日将丢失。

我有2个问题:

  1. 是否可以找到一周结束的一周,如果该周是一个月结束的一周,它会获取“月末”日期?

  2. 如果没有,我是否可以查看周结束表,该表中包含该年的每个周末。通过获取该表中的行来进行某种日期范围的设置吗?

1 个答案:

答案 0 :(得分:2)

如果您可以在日历表(表timecard)中添加一列来存储星期几的日期,这将更加简单。然后,我们可以简单地汇总每个时间间隔内提交的所有样本。

鉴于您当前的数据库设计,一种解决方案是使用相关子查询来模拟此行为。此后,NOT EXISTS条件确保我们将当前的sample记录与相关的timecard记录联接在一起。外部查询按名称和日期间隔进行汇总,HAVING BY子句过滤未达到最小工作小时数的记录。

SELECT
    s.name,
    s.WeekEnding DateEntered,
    t.WeekEnding,
    t.MinimumHours,
    SUM(s.HoursWorked) TotalHoursWorked
FROM sample s
INNER JOIN timecard t 
    ON s.WeekEnding <= t.WeekEnding
    AND NOT EXISTS (
        SELECT 1
        FROM timecard t1
        WHERE s.WeekEnding <= t.WeekEnding AND t1.WeekEnding > t.WeekEnding
    )
GROUP BY
    s.name,
    s.WeekEnding,
    t.WeekStart,
    t.WeekEnding,        
    t.MinimumHours
HAVING SUM(s.HoursWorked) < t.MinimumHours

从SQLServer 2017开始,窗口函数使操作变得更容易。我们可以使用LAG()访问上一条记录:

SELECT
    s.name,
    s.WeekEnding DateEntered,
    t.WeekStart,
    t.WeekEnding,        
    t.MinimumHours,
    SUM(s.HoursWorked) TotalHoursWorked
FROM
    sample s
    INNER JOIN (
        SELECT 
            WeekEnding, 
            MinimumHours, 
            LAG(WeekEnding) OVER(ORDER BY WeekEnding) WeekStart
        FROM timecard
    ) t 
        ON s.WeekEnding > t.WeekStart AND s.WeekEnding <= t.WeekEnding
GROUP BY
    s.name,
    s.WeekEnding,
    t.WeekStart,
    t.WeekEnding,        
    t.MinimumHours