【问题标题】:query to get vacations/sick days last month查询上个月的假期/病假
【发布时间】:2019-09-29 04:30:59
【问题描述】:

我正在使用 laravelsql srv

有些工人有时会休假或请病假 休假日存储在“vacations”表中,而休假的员工详细信息存储在“users”表中。

实际上,vacations 表属于用户,Worker_id 指向用户表的“id”。

有两个表:“users”和“vacations

  1. "users" 具有以下列: id, name

  2. "vacations" 具有以下列: vacation_idworker_idbegin_dateend_datedescription

description 只能有两个值1- vacation, 2-iilness

我想进行一个查询,该查询将分别给出每个用户上个月的总 vacation/iilness 天数

这样输出表将是

Name  | Type    | Total days | 

David | iilness |     2      |

David | vacation|     3      |

Sara  | iilness |     1      |

Sara  | Vacation|     5      |

我发现这个问题可能对答案有所帮助: Retrive all rows from last month (Laravel + Eloquent)

但只是其中的一部分。

【问题讨论】:

    标签: php sql laravel


    【解决方案1】:

    您可以使用JOIN、聚合和DATEDIFF()

    棘手的部分是vacation 表中是否有跨越多个月(并且可能在未来)的期间。要处理这个问题,您可以使用计算当前月份的第一个月和月底的子查询,然后使用它来:

    • 使用JOIN 过滤vacation 表:您要选择开始日期或结束日期属于当前月份的记录

    • 调整SELECT中的计算:如果开始日期在月初之前,您只想从月初开始计算天数;如果结束日期在月底之后,您只想计算到月底

    考虑:

    SELECT
        u.name,
        v.description,
        SUM(DATEDIFF(
            LEAST(v.end_date, m.end_date), 
            GREATEST(v.begin_date, m.begin_date)
        )) total_days
    FROM 
        user u
        INNER JOIN vacation v ON u.id = v.woker_id
        INNER JOIN (
            SELECT 
                LAST_DAY(NOW() - INTERVAL 1 MONTH) + INTERVAL 1 DAY begin_date, 
                LAST_DAY(NOW()) end_date
        ) m
            ON v.begin_date BETWEEN m.begin_date AND m.end_date
            OR v.end_date   BETWEEN m.begin_date AND m.end_date
    GROUP BY u.id, u.name, v.description
    

    以上是针对 MySQL 的。 SQL Server 中日期函数不同的等价物是:

    SELECT
        u.name,
        v.description,
        SUM(DATEDIFF(
            'day',
            CASE WHEN v.begin_date < m.begin_date THEN m.begin_date ELSE v.begin_date END,
            CASE WHEN v.end_date > m.end_date     THEN m.end_date   ELSE v.end_date   END
        )) total_days
    FROM 
        user u
        INNER JOIN vacation v ON u.id = v.woker_id
        INNER JOIN (
            SELECT 
                DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0) begin_date, 
                EOMONTH(GETDATE()) end_date
        ) m
            ON v.begin_date BETWEEN m.begin_date AND m.end_date
            OR v.end_date   BETWEEN m.begin_date AND m.end_date
    GROUP BY u.id, u.name, v.description
    

    【讨论】:

      【解决方案2】:

      最后我找到了以下在 Laravel 上实现的方法

      $query = "
              SELECT
          u.name,
          v.description,
          SUM(DATEDIFF(
              day,
              CASE WHEN v.begin_date < m.begin_date THEN m.begin_date ELSE v.begin_date END,
              CASE WHEN v.end_date > m.end_date     THEN m.end_date   ELSE v.end_date   END
          )+1) total_days
      FROM 
          [turtle].[dbo].[users] u
          INNER JOIN [turtle].[dbo].[vacations] v ON u.id = v.Worker_id
          INNER JOIN (
              SELECT 
                  DATEADD(month, DATEDIFF(month, 0, DATEADD(month,-1,GETDATE())), 0) begin_date, 
                  EOMONTH(DATEADD(month,-1,GETDATE())) end_date
          ) m
              ON v.begin_date BETWEEN m.begin_date AND m.end_date
              OR v.end_date   BETWEEN m.begin_date AND m.end_date
      GROUP BY u.id, u.name, v.description
      ORDER BY u.name, v.description
              ";
      
              $results = DB::select(DB::raw($query));
              dd($results);
      

      【讨论】:

      【解决方案3】:

      对于 sql 服务器:

      尚未对其进行测试,但类似这样的东西可以完成这项工作。

      select name,type,sum(datediff(d,begin_date,end_date)) as Total_days  from vacations v
          inner join users u
          on u.id = v.worker_id
          where begin_date> select dateadd(d,-DATEPART(DD,GETDATE()),GETDATE())
          group by name,type
      

      这仅适用于您所描述的上个月的叶子。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多