SQL 使用 Case 语句分组
SQL group by with Case statement
我有一个 table 看起来像这样
+-----------+-----------+---------------------+
| Report_id | Status | Date |
+-----------+-----------+---------------------+
| 1 | Completed | 2020-06-07 12:20:00 |
| 1 | Completed | 2020-06-07 12:22:00 |
| 2 | Running | 2020-06-07 13:02:00 |
| 2 | Completed | 2020-06-07 13:10:00 |
| 3 | Completed | 2020-06-07 14:10:00 |
| 3 | Failed | 2020-06-07 14:04:00 |
+-----------+-----------+---------------------+
我需要按 Report_id 对这些数据进行分组。因此,如果组内的所有状态值都等于已完成,则 Status 为已完成且 Date 是组内的最大值。但是,如果组内有一个 运行 或 Failed 值,则 Status 需要分别等于 运行 和 Failed 以及 Date 应该匹配这个值。
输出将如下所示。
+-----------+-----------+---------------------+
| Report_id | Status | Date |
+-----------+-----------+---------------------+
| 1 | Completed | 2020-06-07 12:22:00 |
| 2 | Running | 2020-06-07 13:02:00 |
| 3 | Failed | 2020-06-07 14:04:00 |
+-----------+-----------+---------------------+
我怀疑我需要在某处使用 Case 语句来获取此输出,但我不知道如何操作。请帮忙。
查看您的示例,您似乎需要每个报告的第一个状态(基于日期)
select m.*
from my_table m
inner join (
select Report_id, min(date) min_date
from my_table
group by Report_id
) t on t.Report_id = m. and t.min_date = m.date
您可以尝试使用 row_number()
select * from
(
select report_id,status,date, row_number() over(partition by report_id order by
case when status in ('Running','Failed') then 1 else 2 end asc,Date desc) as rn
from tablename
)A where rn=1
您可以使用 STRING_AGG 将状态列的文本组合成一个字符串,并检查该字符串是否包含 'running' 或 'failed'
select report_id,
case when STRING_AGG(status, '') like '%Running%' then 'Running'
when STRING_AGG(status, '') like '%Failed%' then 'Failed'
else 'Completed' end Status,
max(date) Date
from abc
group by report_id
不确定这是否是您要查找的内容,也不确定这是否完全 运行。
select report_id,
case when q.failed_sum > 0 then 'Failed'
when q.running_sum > 0 then 'Running'
else 'Completed'
end,
max(date)
from table inner join
(
select report_id,
sum(case when status = 'Failed' then 1 end) as failed_sum,
sum(case when status = 'Running' then 1 end) as running_sum,
sum(case when status = 'Completed' then 1 end)as completed_sum
from table
group by report_id
)q on report_id = q.report_id
where status = (case when failed_sum > 0 then 'Failed'
else when running_sum > 0 then 'Running'
else then 'Completed'
end)
group by report_id
您可以使用 distinct on
:
select distinct on (record_id) t.*
from t
order by (case when status <> 'Completed' then 1 else 2 end),
date desc;
我有一个 table 看起来像这样
+-----------+-----------+---------------------+
| Report_id | Status | Date |
+-----------+-----------+---------------------+
| 1 | Completed | 2020-06-07 12:20:00 |
| 1 | Completed | 2020-06-07 12:22:00 |
| 2 | Running | 2020-06-07 13:02:00 |
| 2 | Completed | 2020-06-07 13:10:00 |
| 3 | Completed | 2020-06-07 14:10:00 |
| 3 | Failed | 2020-06-07 14:04:00 |
+-----------+-----------+---------------------+
我需要按 Report_id 对这些数据进行分组。因此,如果组内的所有状态值都等于已完成,则 Status 为已完成且 Date 是组内的最大值。但是,如果组内有一个 运行 或 Failed 值,则 Status 需要分别等于 运行 和 Failed 以及 Date 应该匹配这个值。
输出将如下所示。
+-----------+-----------+---------------------+
| Report_id | Status | Date |
+-----------+-----------+---------------------+
| 1 | Completed | 2020-06-07 12:22:00 |
| 2 | Running | 2020-06-07 13:02:00 |
| 3 | Failed | 2020-06-07 14:04:00 |
+-----------+-----------+---------------------+
我怀疑我需要在某处使用 Case 语句来获取此输出,但我不知道如何操作。请帮忙。
查看您的示例,您似乎需要每个报告的第一个状态(基于日期)
select m.*
from my_table m
inner join (
select Report_id, min(date) min_date
from my_table
group by Report_id
) t on t.Report_id = m. and t.min_date = m.date
您可以尝试使用 row_number()
select * from
(
select report_id,status,date, row_number() over(partition by report_id order by
case when status in ('Running','Failed') then 1 else 2 end asc,Date desc) as rn
from tablename
)A where rn=1
您可以使用 STRING_AGG 将状态列的文本组合成一个字符串,并检查该字符串是否包含 'running' 或 'failed'
select report_id,
case when STRING_AGG(status, '') like '%Running%' then 'Running'
when STRING_AGG(status, '') like '%Failed%' then 'Failed'
else 'Completed' end Status,
max(date) Date
from abc
group by report_id
不确定这是否是您要查找的内容,也不确定这是否完全 运行。
select report_id,
case when q.failed_sum > 0 then 'Failed'
when q.running_sum > 0 then 'Running'
else 'Completed'
end,
max(date)
from table inner join
(
select report_id,
sum(case when status = 'Failed' then 1 end) as failed_sum,
sum(case when status = 'Running' then 1 end) as running_sum,
sum(case when status = 'Completed' then 1 end)as completed_sum
from table
group by report_id
)q on report_id = q.report_id
where status = (case when failed_sum > 0 then 'Failed'
else when running_sum > 0 then 'Running'
else then 'Completed'
end)
group by report_id
您可以使用 distinct on
:
select distinct on (record_id) t.*
from t
order by (case when status <> 'Completed' then 1 else 2 end),
date desc;