CASE 子句中的计数条件
Count condition in CASE clause
我正在尝试根据 SQL 查询中错误代码的计数及其在特定时间段内的出现次数获取条件值,但是我编写的这个查询 returns 第一个满足的条件对于所有记录。
我做错了什么
SELECT ERROR_CODE,
CASE
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 2)
AND ERROR_CODE = '50001') > 50 THEN 'RED'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 2)
AND ERROR_CODE = '50001') < 50 THEN 'GREEN'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 1)
AND ERROR_CODE IS NULL) > 100 THEN 'RED'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 1)
AND ERROR_CODE IS NULL) < 100 THEN 'GREEN'
END AS ALERT_COLOR
FROM ERROR_LOG
GROUP BY ERROR_CODE
样本数据
50005 05-JAN-15 11.05.51.570000000 AM
50001 05-JAN-15 02.39.57.840000000 PM
50001 05-JAN-15 02.31.06.700000000 PM
50001 05-JAN-15 02.21.49.350000000 PM
50001 05-JAN-15 01.59.13.910000000 PM
50001 05-JAN-15 01.50.05.900000000 PM
50001 05-JAN-15 01.30.19.270000000 PM
50001 05-JAN-15 01.11.10.510000000 PM
50001 05-JAN-15 12.00.00.720000000 PM
05-JAN-15 09.42.10.670000000 AM
05-JAN-15 09.37.31.590000000 AM
DESIRED OUPUT(更改计数条件以查看所需输出)
计数
2
50001 8
50005 1
SQL
SELECT ERROR_CODE,
CASE
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 2)
AND ERROR_CODE = '50001') between 5 and 100 THEN 'RED'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 2)
AND ERROR_CODE = '50001') < 5 THEN 'GREEN'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 1)
AND ERROR_CODE IS NULL) > 100 THEN 'RED'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 1)
AND ERROR_CODE IS NULL) between 5 and 100 THEN 'GREEN'
END AS ALERT_COLOR
FROM ERROR_LOG
GROUP BY ERROR_CODE
结果
Error_code Alert_color
GREEN
50005 ''
50001 RED
case
Returns 计算结果为 TRUE
的第一个 input_expression = when_expression
的 result_expression
。试试这个。
SELECT ERROR_CODE,
CASE
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 2)
AND ERROR_CODE = '50001') between 50 and 100 THEN 'RED'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 2)
AND ERROR_CODE = '50001') < 50 THEN 'GREEN'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 1)
AND ERROR_CODE IS NULL) > 100 THEN 'RED'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 1)
AND ERROR_CODE IS NULL) between 50 and 100 THEN 'GREEN'
END AS ALERT_COLOR
FROM ERROR_LOG
GROUP BY ERROR_CODE
您正在为 table 中的每一行重复每个 when
子句中的子查询,没有相关性。子查询:
(SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 2)
AND ERROR_CODE = '50001')
... 每次都会对 table 中的每一行求值为 8;因此,无论该行中实际的错误代码如何,案例的第一个分支将始终匹配,因此您会看到每一行的 RED
。
重复子查询效率低下,即使您关联了它。 Oracle 会 optimise/cache 它,但仍然......最好生成一次计数:
select error_code,
count(case when cret_dtim > trunc(sysdate - 2) then 1 end) as cnt_2_day,
count(case when cret_dtim > trunc(sysdate - 1) then 1 end) as cnt_1_day
from error_log
where cret_dtim > trunc(sysdate - 2)
group by error_code
order by error_code nulls first;
ERROR_CODE CNT_2_DAY CNT_1_DAY
---------- --------- ----------
(null) 2 2
50001 8 8
50005 1 1
您的所有样本数据都不到一天,因此计数相同;如果您有两天前的数据,它们会有所不同。
然后您可以将其用作内部查询(或 CTE,如果您愿意)并将结果用作另一级别 case
的输入以转换为您的颜色代码:
select error_code,
case
when error_code = '50001' and cnt_1_day between 5 and 100 then 'RED'
when error_code = '50001' and cnt_2_day < 5 then 'GREEN'
when error_code is null and cnt_1_day > 100 then 'RED'
when error_code is null and cnt_1_day between 5 and 100 then 'GREEN'
else null
end as alert_colour
from
(
select error_code,
count(case when cret_dtim > trunc(sysdate - 2) then 1 end) as cnt_2_day,
count(case when cret_dtim > trunc(sysdate - 1) then 1 end) as cnt_1_day
from error_log
where cret_dtim > trunc(sysdate - 2)
group by error_code
)
order by error_code nulls first;
ERROR_CODE ALERT_COLOUR
---------- ------------
(null) (null)
50001 RED
50005 (null)
这与您所说的预期结果不符,但正如我在评论中所说,我不确定您是如何从数字中得出所显示的结果的。你的桶排除了很多可能性;例如,您可能希望第一个条件只是 > 5
。您完全忽略了您希望看到的 50005
。如果您的基本逻辑是任何代码集使用 2 天计数而空值使用 1 天计数——这是一个飞跃——那么您可以将其概括为:
select error_code,
case
when error_code is not null and cnt_not_null between 5 and 100 then 'RED'
when error_code is not null and cnt_not_null < 5 then 'GREEN'
when error_code is null and cnt_null > 100 then 'RED'
when error_code is null and cnt_null between 5 and 100 then 'GREEN'
else null
end as alert_colour
from (
select error_code,
count(case when cret_dtim > trunc(sysdate - 2)
and error_code is not null then 1 end) as cnt_not_null,
count(case when cret_dtim > trunc(sysdate - 1)
and error_code is null then 1 end) as cnt_null
from error_log
where cret_dtim > trunc(sysdate - 2)
group by error_code
)
order by error_code nulls first;
ERROR_CODE ALERT_COLOUR
---------- ------------
(null) (null)
50001 RED
50005 GREEN
这仍然不是您的预期结果,但在解释逻辑(和我的错误)或更改您的结果之前必须这样做...
我正在尝试根据 SQL 查询中错误代码的计数及其在特定时间段内的出现次数获取条件值,但是我编写的这个查询 returns 第一个满足的条件对于所有记录。
我做错了什么
SELECT ERROR_CODE,
CASE
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 2)
AND ERROR_CODE = '50001') > 50 THEN 'RED'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 2)
AND ERROR_CODE = '50001') < 50 THEN 'GREEN'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 1)
AND ERROR_CODE IS NULL) > 100 THEN 'RED'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 1)
AND ERROR_CODE IS NULL) < 100 THEN 'GREEN'
END AS ALERT_COLOR
FROM ERROR_LOG
GROUP BY ERROR_CODE
样本数据
50005 05-JAN-15 11.05.51.570000000 AM
50001 05-JAN-15 02.39.57.840000000 PM
50001 05-JAN-15 02.31.06.700000000 PM
50001 05-JAN-15 02.21.49.350000000 PM
50001 05-JAN-15 01.59.13.910000000 PM
50001 05-JAN-15 01.50.05.900000000 PM
50001 05-JAN-15 01.30.19.270000000 PM
50001 05-JAN-15 01.11.10.510000000 PM
50001 05-JAN-15 12.00.00.720000000 PM
05-JAN-15 09.42.10.670000000 AM
05-JAN-15 09.37.31.590000000 AM
DESIRED OUPUT(更改计数条件以查看所需输出) 计数
2
50001 8
50005 1
SQL
SELECT ERROR_CODE,
CASE
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 2)
AND ERROR_CODE = '50001') between 5 and 100 THEN 'RED'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 2)
AND ERROR_CODE = '50001') < 5 THEN 'GREEN'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 1)
AND ERROR_CODE IS NULL) > 100 THEN 'RED'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 1)
AND ERROR_CODE IS NULL) between 5 and 100 THEN 'GREEN'
END AS ALERT_COLOR
FROM ERROR_LOG
GROUP BY ERROR_CODE
结果
Error_code Alert_color
GREEN
50005 ''
50001 RED
case
Returns 计算结果为 TRUE
的第一个 input_expression = when_expression
的 result_expression
。试试这个。
SELECT ERROR_CODE,
CASE
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 2)
AND ERROR_CODE = '50001') between 50 and 100 THEN 'RED'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 2)
AND ERROR_CODE = '50001') < 50 THEN 'GREEN'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 1)
AND ERROR_CODE IS NULL) > 100 THEN 'RED'
WHEN (SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 1)
AND ERROR_CODE IS NULL) between 50 and 100 THEN 'GREEN'
END AS ALERT_COLOR
FROM ERROR_LOG
GROUP BY ERROR_CODE
您正在为 table 中的每一行重复每个 when
子句中的子查询,没有相关性。子查询:
(SELECT Count(ERROR_CODE)
FROM ERROR_LOG
WHERE CRET_DTIM > Trunc(SYSDATE - 2)
AND ERROR_CODE = '50001')
... 每次都会对 table 中的每一行求值为 8;因此,无论该行中实际的错误代码如何,案例的第一个分支将始终匹配,因此您会看到每一行的 RED
。
重复子查询效率低下,即使您关联了它。 Oracle 会 optimise/cache 它,但仍然......最好生成一次计数:
select error_code,
count(case when cret_dtim > trunc(sysdate - 2) then 1 end) as cnt_2_day,
count(case when cret_dtim > trunc(sysdate - 1) then 1 end) as cnt_1_day
from error_log
where cret_dtim > trunc(sysdate - 2)
group by error_code
order by error_code nulls first;
ERROR_CODE CNT_2_DAY CNT_1_DAY
---------- --------- ----------
(null) 2 2
50001 8 8
50005 1 1
您的所有样本数据都不到一天,因此计数相同;如果您有两天前的数据,它们会有所不同。
然后您可以将其用作内部查询(或 CTE,如果您愿意)并将结果用作另一级别 case
的输入以转换为您的颜色代码:
select error_code,
case
when error_code = '50001' and cnt_1_day between 5 and 100 then 'RED'
when error_code = '50001' and cnt_2_day < 5 then 'GREEN'
when error_code is null and cnt_1_day > 100 then 'RED'
when error_code is null and cnt_1_day between 5 and 100 then 'GREEN'
else null
end as alert_colour
from
(
select error_code,
count(case when cret_dtim > trunc(sysdate - 2) then 1 end) as cnt_2_day,
count(case when cret_dtim > trunc(sysdate - 1) then 1 end) as cnt_1_day
from error_log
where cret_dtim > trunc(sysdate - 2)
group by error_code
)
order by error_code nulls first;
ERROR_CODE ALERT_COLOUR
---------- ------------
(null) (null)
50001 RED
50005 (null)
这与您所说的预期结果不符,但正如我在评论中所说,我不确定您是如何从数字中得出所显示的结果的。你的桶排除了很多可能性;例如,您可能希望第一个条件只是 > 5
。您完全忽略了您希望看到的 50005
。如果您的基本逻辑是任何代码集使用 2 天计数而空值使用 1 天计数——这是一个飞跃——那么您可以将其概括为:
select error_code,
case
when error_code is not null and cnt_not_null between 5 and 100 then 'RED'
when error_code is not null and cnt_not_null < 5 then 'GREEN'
when error_code is null and cnt_null > 100 then 'RED'
when error_code is null and cnt_null between 5 and 100 then 'GREEN'
else null
end as alert_colour
from (
select error_code,
count(case when cret_dtim > trunc(sysdate - 2)
and error_code is not null then 1 end) as cnt_not_null,
count(case when cret_dtim > trunc(sysdate - 1)
and error_code is null then 1 end) as cnt_null
from error_log
where cret_dtim > trunc(sysdate - 2)
group by error_code
)
order by error_code nulls first;
ERROR_CODE ALERT_COLOUR
---------- ------------
(null) (null)
50001 RED
50005 GREEN
这仍然不是您的预期结果,但在解释逻辑(和我的错误)或更改您的结果之前必须这样做...