我有一个包含1069行的数据库。有一个名为TRIAL_ID
的列,其中包含该人在不同位置的标识符。以下是该列的示例:
TRIAL_ID
OAD001
OAD010
OAD501
ROT002
ROT008
ROT903
JAC3ODF
BA39SD
MK2093
如果您注意到,前三个来自位置OAD
,后三个来自位置ROT
,其余的 no pattern 来自第三位置。
我想做的是显示每个位置的计数。以下是我尝试的方法:
select (
select count(trial_id) from locations where trial_id like 'oad%'),
(select count(trial_id) from locations where trial_id like 'rot%'),
(select count(trial_id) from locations where trial_id not like 'rot%' or trial_id not like 'oad%')
from locations
但是,这正确地显示了oad
和rot
的数量,但没有显示第三个。另外,它显示的计数是locations
表中的行数的两倍。
如何只获取每种类型的计数?
答案 0 :(得分:1)
您的版本失败的原因是or
应该是and
。 not
和布尔逻辑很棘手。
但是,条件聚合是一种更好的方法:
select sum(case when trial_id like 'oad%' then 1 else 0 end) as oad,
sum(case when trial_id like 'rot%' then 1 else 0 end) as rot,
sum(case when trial_id not like 'oad%' and trial_id not like 'rot%' then 1 else 0 end) as other
from locations;
更好,因为它对所有计算只扫描一次表。
此查询以单行返回结果,其中三列为计数。您的版本将在每个位置单独显示一行,并在每一行重复计数。
您也可以使用group by
来表达这一点:
select (case when trial_id like 'oad%' then 'oad'
when trial_id like 'rot%' then 'rot'
else 'other'
end) as location,
count(*)
from locations
group by (case when trial_id like 'oad%' then 'oad'
when trial_id like 'rot%' then 'rot'
else 'other'
end);
这将返回结果(最多)三行。
答案 1 :(得分:1)
您需要在此处使用条件聚合:
SELECT
COUNT(CASE WHEN trial_id LIKE 'oad%' THEN 1 END) AS oad_cnt,
COUNT(CASE WHEN trial_id LIKE 'rot%' THEN 1 END) AS rot_cnt,
COUNT(CASE WHEN trial_id NOT LIKE 'oad%' AND trial_id NOT LIKE 'rot%'
THEN 1 END) AS other_cnt
FROM locations;
注意:我选择在这里使用COUNT
而不是SUM
,因为使用前者可以避免出现明显的ELSE
条件,从而使代码更短,更整洁。阅读。
答案 2 :(得分:1)
更通用的一个?
SQL> with test (trial_id) as
2 (select 'OAD001' from dual union all
3 select 'OAD010' from dual union all
4 select 'OAD501' from dual union all
5 select 'ROT002' from dual union all
6 select 'ROT008' from dual union all
7 select 'ROT903' from dual union all
8 select 'JAC30F' from dual union all
9 select 'BA395D' from dual union all
10 select 'MK2093' from dual
11 )
12 select case when substr(trial_id, 1, 3) in ('OAD', 'ROT') then substr(trial_id, 1, 3)
13 else 'no pattern'
14 end location,
15 count(*) cnt
16 from test
17 group by
18 case when substr(trial_id, 1, 3) in ('OAD', 'ROT') then substr(trial_id, 1, 3)
19 else 'no pattern'
20 end;
LOCATION CNT
------------ ----------
OAD 3
ROT 3
no pattern 3
SQL>
答案 3 :(得分:0)
您使用了错误的逻辑运算符-您需要计算不以rot
开头的行和不以oad
开头的行。或者,在SQL中:
trial_id not like 'rot%' AND trial_id not like 'oad%'
// -- Here --------------^