【问题标题】:Shift manipulation in SQL to get countsSQL 中的移位操作以获取计数
【发布时间】:2014-07-30 12:06:53
【问题描述】:

我参加了下表Attendance

EID 是员工 ID,在班次栏中,D 表示白班,N 表示夜班。

现在我正在尝试获取与每个员工有关的以下数据。

白班次数 - D 的计数, 夜班次数 - N 的计数, 工作天数 - 员工在任一班次或两个班次中工作的天数(即使是员工在同一天同时工作,也视为一天。)

我可以在三个不同的结果中获得所有三个信息,如下所示...

WITH CTE (EID, in_time, shift) AS  
(
SELECT EID, in_time, shift FROM Attendance 
WHERE (in_time BETWEEN CONVERT(DATETIME, '2014-01-07 00:00:00', 102) AND CONVERT(DATETIME, '2014-07-31 00:00:00', 102)) AND PID = 'A002'
)

SELECT     EID, COUNT(*) AS DayTotal 
FROM         CTE
WHERE     (shift = 'D')
GROUP BY EID

SELECT     EID, COUNT(*) AS NightTotal 
FROM         Attendance
WHERE     (shift = 'N')
GROUP BY EID
;

WITH CTE2 (EID, in_time, shift) AS  
(
SELECT EID, in_time, shift FROM Attendance 
WHERE (in_time BETWEEN CONVERT(DATETIME, '2014-01-07 00:00:00', 102) AND CONVERT(DATETIME, '2014-07-31 00:00:00', 102)) AND PID = 'A002'
)
SELECT EID, COUNT ( DISTINCT CONVERT (DATE, in_time)) AS [Days] 
FROM CTE2 
WHERE (shift = 'D' OR shift = 'N')
GROUP BY EID

但我想在单个结果(表)中使用它。所以我尝试了以下查询,但它没有给出预期的输出。

WITH CTE (EID, in_time, shift) AS  
(
SELECT EID, in_time, shift FROM Attendance 
WHERE (in_time BETWEEN CONVERT(DATETIME, '2014-01-07 00:00:00', 102) AND CONVERT(DATETIME, '2014-07-31 00:00:00', 102)) AND PID = 'A002'
)

SELECT EID, 
CASE WHEN Shift = 'D' THEN COUNT(Shift) END AS [Day],
CASE WHEN Shift = 'N' THEN COUNT(Shift) END AS [Night],   
COUNT ( DISTINCT CONVERT (DATE, in_time)) AS [Days]  
FROM         CTE 
GROUP BY EID, shift

您能告诉我一个方法吗?

预期结果

【问题讨论】:

    标签: sql sql-server ado.net case common-table-expression


    【解决方案1】:

    我认为你可以使用条件聚合得到你想要的:

    SELECT EID,
           sum(case when shift = 'd' then 1 else 0 end) as dayshifts,
           sum(case when shift = 'n' then 1 else 0 end) as nightshifts,
           count(*) as total
    FROM Attendance a
    WHERE (in_time BETWEEN CONVERT(DATETIME, '2014-01-07 00:00:00', 102) AND
                           CONVERT(DATETIME, '2014-07-31 00:00:00', 102)) AND
          PID = 'A002';
    

    编辑:

    如果您想计算不同日期的总数,请使用count(distinct)

    SELECT EID,
           sum(case when shift = 'd' then 1 else 0 end) as dayshifts,
           sum(case when shift = 'n' then 1 else 0 end) as nightshifts,
           count(distinct case when shift in ('d', 'n') then cast(in_time as date) end) as total
    FROM Attendance a
    WHERE (in_time BETWEEN CONVERT(DATETIME, '2014-01-07 00:00:00', 102) AND
                           CONVERT(DATETIME, '2014-07-31 00:00:00', 102)) AND
          PID = 'A002';
    

    【讨论】:

    • 如果有人同时上夜班,会不会在“总计”列中计算两次?
    • 吉迪尔是正确的。它不应该计算两次。谢谢
    • 第 4 行第一个 cast 应该是 case。现在它起作用了。谢谢。
    • @Chathuranga 。 . .谢谢你。固定。
    【解决方案2】:
    WITH cte (eid, in_time, shift) 
         AS (SELECT eid, 
                    in_time, 
                    shift 
             FROM   attendance 
             WHERE  ( in_time BETWEEN CONVERT(DATETIME, '2014-01-07 00:00:00', 102) 
                                      AND 
                                                CONVERT(DATETIME, 
                                                '2014-07-31 00:00:00', 
                                                102 
                                                ) ) 
                    AND pid = 'A002') 
    
    SELECT eid, 
           Sum(CASE 
                   WHEN shift = 'D' THEN 1 
                   ELSE 0 
                 END)                               AS DayTotal, 
           Sum(CASE 
                   WHEN shift = 'N' THEN 1 
                   ELSE 0 
                 END)                               AS NightTotal, 
           Count (DISTINCT CONVERT (DATE, in_time)) AS Days 
    FROM   cte 
    GROUP  BY eid 
    

    【讨论】:

    • 它有效,但结果数字不匹配。嗯,价值观不现实,但条件似乎还可以?我会试一试。谢谢。
    • 当 count 以这种方式使用时,它不关心条件并给出两个班次的计数。如果使用 sum 代替,它会给出正确的结果。但我不知道原因;)
    【解决方案3】:

    @Chathuranga,由于一天的日班和夜班应该算作一个,请让我知道以下解决方案是否适合您。

    DECLARE @Attendance TABLE (EID INT,
                          PID CHAR(4),
                          In_Time DATETIME,
                          Out_Time DATETIME,
                          Shift CHAR(1))
    
    INSERT INTO @Attendance
    VALUES
    ('100', 'A001', '2014-07-01 07:00:00.000', '2014-07-01 19:30:00.000', 'D'),
    ('102', 'A001', '2014-07-01 19:30:00.000', '2014-07-02 07:00:00.000', 'N'),
    ('100', 'A001', '2014-07-01 19:30:00.000', '2014-07-02 07:00:00.000', 'N'),
    ('104', 'A001', '2014-07-02 07:00:00.000', '2014-07-02 19:30:00.000', 'D'),
    ('100', 'A001', '2014-07-03 19:30:00.000', '2014-07-04 07:00:00.000', 'N'),
    ('102', 'A001', '2014-07-03 19:30:00.000', '2014-07-04 07:00:00.000', 'N'),
    ('104', 'A001', '2014-07-03 07:00:00.000', '2014-07-03 19:30:15.000', 'D'),
    ('102', 'A001', '2014-07-04 07:00:00.000', '2014-07-04 19:30:00.000', 'D'),
    ('100', 'A001', '2014-07-04 07:00:00.000', '2014-07-04 19:30:10.000', 'D')
    
    SELECT EID,
          SUM(CASE
                  WHEN Shift = 'D' THEN 1
                  ELSE 0
              END) AS DayShift,
          SUM(CASE
                  WHEN Shift = 'N' THEN 1
                  ELSE 0
              END) AS NightShift,
          COUNT(DISTINCT CAST(In_Time AS DATE)) AS DayTotal
    FROM @Attendance
    GROUP BY EID
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-25
      • 1970-01-01
      • 1970-01-01
      • 2022-11-17
      • 1970-01-01
      相关资源
      最近更新 更多