如何使用PL / SQL在单个列中获得相似标识符的计数

时间:2018-12-08 15:27:45

标签: sql oracle plsql

我有一个包含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

但是,这正确地显示了oadrot的数量,但没有显示第三个。另外,它显示的计数是locations表中的行数的两倍。

如何只获取每种类型的计数?

4 个答案:

答案 0 :(得分:1)

您的版本失败的原因是or应该是andnot和布尔逻辑很棘手。

但是,条件聚合是一种更好的方法:

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 --------------^