Oracle Sql中带有聚合函数的情况

问题描述 投票:0回答:2

我有一个带有用户每月出勤详细信息的表,其中有一个加班列。因此,该表具有以下结构和示例数据:

Date      - Id   - Dept - OT - Status
12/1/2019 - 1001 - HR   - 2  - P
12/2/2019 - 1001 - HR   - 4  - P 
12/1/2019 - 1002 - IT   - 2  - P
12/2/2019 - 1002 - IT   - 4  - P 

我在这里省略了进出时间,因为这不是这里的主要问题。参见上文,计算了每个用户的加班时间。因此,可以很容易地按如下方式计算用户或部门的总加班详细信息:

SELECT DEPT, SUM(OT) TOTAL FROM ATTENDANCE m WHERE M.DATE >= '01-DEC-2019' AND M.DATE <= '10-DEC-2019'
GROUP BY M.DEPT

我的要求是获取具有特定日期范围的部门的每周或7天加班详细信息,加班范围为40。例如:对于一个部门,日期范围为2019年12月1日至7日,总加班时间将长达40小时或41至50小时。所以我尝试了以下方法:

SELECT DEPT, SUM(OT) TOTAL FROM ATTENDANCE m WHERE M.DATE >= '01-DEC-2019' AND M.DATE <= '07-DEC-2019'
HAVING SUM(OT) <= 40 GROUP BY M.DEPT

或:

SELECT DEPT, SUM(OT) TOTAL FROM ATTENDANCE m WHERE M.DATE >= '01-DEC-2019' AND M.DATE <= '07-DEC-2019'
HAVING SUM(OT) BETWEEN 41 AND 50 GROUP BY M.DEPT

或:

SELECT DEPT, SUM(OT) TOTAL FROM ATTENDANCE m WHERE M.DATE >= '01-DEC-2019' AND M.DATE <= '07-DEC-2019'
HAVING SUM(OT) > 50 GROUP BY M.DEPT

但是最后一个查询似乎返回了奇怪的输出,并且似乎返回了我在第一个查询中检索到的数据。这些是我很累的单独查询,但我在考虑是否可以使用子查询通过上述所有范围将其与CASE WHEN配合使用:

CASE WHEN M.DATE >= '01-DEC-2019' AND M.DATE <= '07-DEC-2019'
AND SUM(OT) <= 40 THEN SUM(OT) 
CASE WHEN M.DATE >= '01-DEC-2019' AND M.DATE <= '07-DEC-2019'
AND SUM(OT) BETWEEN 41 AND 50 THEN SUM(OT) 

我不确定是否可以将聚集函数与CASE WHEN语句一起使用,或者可以使用上述任何方法在查询中运行多个范围?谢谢。

sql oracle oracle10g
2个回答
0
投票

您可以使用CASE区分所有值。例如:

select 
  dept, 
  sum(ot) as total,
  case when sum(ot) <= 40 then 'g1'
       when sum(ot) > 40 and sum(ot) <= 50 then 'g2'
       else 'g3' end as g
from attendance
where date >= '01-dec-2019' and date <= '07-dec-2019'
group by dept

0
投票

您可以更明确地说明所需的输出是什么吗?您似乎正在寻找两个结果(在指定的日期范围内,加班时间为[[> 40小时的部门,以及加班时间为[[over] 40小时的部门)?]

查看您的上一个查询:CASE WHEN M.DATE >= '01-DEC-2019' AND M.DATE <= '07-DEC-2019' AND SUM(OT) <= 40 THEN SUM(OT) CASE WHEN M.DATE >= '01-DEC-2019' AND M.DATE <= '07-DEC-2019' AND SUM(OT) BETWEEN 41 AND 50 THEN SUM(OT)

鉴于应用的日期范围是相同的,您可以将其移到WHERE子句吗?然后,您可以使用子查询或其他方法将部门按使用了多少加班时间分组(类似这样):

SELECT
    Dept
    , CASE
        WHEN TotalOvertime <= 40 THEN 'something'
        WHEN (TotalOvertime > 40 AND <= 50) THEN 'something_else'
        ELSE 'exception'
    END AS OvertimeCaseStatement
FROM (
SELECT Dept
    , SUM(OT) AS TotalOvertime
FROM Attendance
WHERE Date BETWEEN '01-DEC-2019' AND '07-DEC-2019'
GROUP BY Dept
)
;

我在您的int比较中也删除了BETWEEN运算符,因为我认为使用逻辑运算符更容易理解[[bit

BETWEEN是包含运算符),并添加了一些错误的名称,例如somethingsomething_else等,您可以更改这些名称以获得更多描述性名称。
请让我知道我是否正在解决您的实际问题,以及这种方法是否存在新的错误/问题!

同样是FWIW,如果Date列是日期而不是字符串,则可能有助于CAST您的参数('01-DEC-2019'等)成为日期类型。希望这会有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.