提问人:basrood 提问时间:11/6/2023 更新时间:11/7/2023 访问量:43
GROUP BY 两列,并根据 SQL 中的条件返回第三列值
GROUP BY two columns and return a third column values based on condition in SQL
问:
我有一些数据由date_time、job_name和状态列组成。这些作业可以每天运行一次,也可以每天在不同时刻运行多次,它们会导致“成功”、“失败”或“禁用”状态。
我的数据如下所示:
date_time | job_name | 地位 |
---|---|---|
01/01/2020 07:30:30 | job_1 | 成功 |
01/01/2020 15:30:30 | job_1 | 禁用 |
01/01/2020 18:30:30 | job_1 | 失败 |
01/01/2020 08:30:30 | job_2 | 成功 |
01/01/2020 18:30:30 | job_2 | 禁用 |
01/02/2020 15:30:30 | job_1 | 成功 |
01/02/2020 08:30:30 | job_2 | 成功 |
01/02/2020 18:30:30 | job_2 | 成功 |
我正在尝试按日期(注意,而不是日期/时间)和job_name对这些数据进行分组。每个日期(注意,不是日期/时间)我想返回作业是否成功。
如果某一天作业的一次运行(或唯一一次运行)为“失败”,则无论当天的其他“状态”结果如何,我的分组行都必须返回“失败”。
如果某一天作业的一次运行(或唯一一次运行)为“已禁用”,并且当天该作业没有“失败”运行,则分组行必须返回“已禁用”。
如果一天内作业的所有运行都是“成功”,则分组行必须返回“成功”。
因此,我的示例表的预期结果为:
date_time | job_name | 地位 |
---|---|---|
01/01/2020 | job_1 | 失败 |
01/01/2020 | job_2 | 禁用 |
01/02/2020 | job_1 | 成功 |
01/02/2020 | job_2 | 成功 |
我尝试在 date_time 和 job_name 列上使用 GROUP BY 语句来获得此结果,但我无法实现何时返回“成功”、“失败”和“禁用”状态的逻辑。
任何帮助都是值得赞赏的!
答:
2赞
Tim Biegeleisen
11/6/2023
#1
使用条件聚合,我们可以尝试:
SELECT
DATE(date_time) AS date_time,
job_name,
CASE WHEN COUNT(CASE WHEN status = 'failed' THEN 1 END) > 0
THEN 'failed'
WHEN COUNT(CASE WHEN status = 'disabled' THEN 1 END) > 0
THEN 'disabled'
WHEN COUNT(CASE WHEN status != 'success' THEN 1 END) = 0
THEN 'success' END AS status
FROM yourTable
GROUP BY
DATE(date_time),
job_name
ORDER BY
DATE(date_time),
job_name;
评论
0赞
Ann L.
11/7/2023
这些不应该是陈述吗?即使 case 语句产生 NULL,您也不会获得 COUNT() 的值吗?SUM(CASE WHEN ... )
0赞
Ann L.
11/7/2023
但如果你没有信心,你可能不会这样写,而且你确实有 505K 分。:)
1赞
Tim Biegeleisen
11/7/2023
@AnnL。我更喜欢在这里使用,而不是因为前者避免了表达。COUNT()
SUM()
ELSE
0赞
basrood
11/7/2023
谢谢,这个和 Xmehdi 的回答奏效了!
0赞
XM01 - stands with Palestine
11/7/2023
#2
结合使用 with 语句、聚合函数和:GROUP BY
CASE
COUNT
SUM
SELECT
CONVERT(DATE, date_time) AS date, --to extract only the date portion from the date_time column.
job_name,
CASE
WHEN COUNT(*) = SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) THEN 'failed'
WHEN SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) > 0 THEN 'failed'
WHEN SUM(CASE WHEN status = 'disabled' THEN 1 ELSE 0 END) > 0 THEN 'disabled'
ELSE 'success'
END AS status
FROM your_table
GROUP BY CONVERT(DATE, date_time), job_name;
这是聚合函数的替代方案:MAX
SELECT
CONVERT(DATE, date_time) AS date,
job_name,
CASE
WHEN MAX(CASE WHEN status = 'failed' THEN 2 WHEN status = 'disabled' THEN 1 ELSE 0 END) = 2 THEN 'failed'
WHEN MAX(CASE WHEN status = 'disabled' THEN 1 ELSE 0 END) = 1 THEN 'disabled'
ELSE 'success'
END AS status
FROM your_table
GROUP BY CONVERT(DATE, date_time), job_name;
评论
1赞
Ann L.
11/7/2023
这与Tim Biegeleisen的回答有何不同?
1赞
Tim Biegeleisen
11/7/2023
此答案不会明确检查所有记录是否都匹配。这可能是一个可行的假设,也可能不是一个可行的假设。success
0赞
XM01 - stands with Palestine
11/7/2023
实际上,我也使用了聚合函数,请查看:MAX
0赞
Ann L.
11/7/2023
#3
为了完整起见,这里有另一个解决方案,一个使用 PIVOT 的解决方案。我无法预测哪种解决方案可能表现得更好:你必须进行实验。
SELECT [date]
, job_name
, CASE
WHEN [failed] > 0
THEN 'failed'
WHEN [disabled] > 0 and [failed] = 0
THEN 'disabled'
WHEN [disabled] = 0 and [failed] = 0 and [success] > 0
THEN 'success'
END as status
FROM (
SELECT
CONVERT(DATE, date_time) as [date]
, job_name
, status
from your_table
) as v
PIVOT (COUNT(status)
FOR status IN (success, failed, disabled)) as c
ORDER BY
[date]
, job_name
DBFiddle(基于 XMedhi01 设置的示例)
评论