Как подсчитать аналогичный идентификатор в одном столбце с помощью PL / SQL - PullRequest
0 голосов
/ 08 декабря 2018

У меня есть база данных с 1069 строками.Есть столбец с именем TRIAL_ID, в котором указан идентификатор человека из другого места.Ниже приведен пример столбца:

TRIAL_ID
OAD001
OAD010
OAD501
ROT002
ROT008
ROT903
JAC3ODF
BA39SD
MK2093

Если вы заметили, первые три из местоположения OAD, а вторые три из местоположения ROT, а остальные с нетшаблон из третьего местоположения.

Что я хочу сделать, это показать счетчик для каждого местоположения.Вот что я попробовал:

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.

Как я могу получить счет только для каждого типа?

Ответы [ 4 ]

0 голосов
/ 08 декабря 2018

Более общий?

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>
0 голосов
/ 08 декабря 2018

Здесь необходимо использовать условное агрегирование:

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таким образом, код становится немного короче и удобнее для чтения.

0 голосов
/ 08 декабря 2018

У вас неправильный логический оператор - вам нужно посчитать строки, которые не начинаются с rot , а не начинаются с oad.Или в SQL:

trial_id not like 'rot%' AND trial_id not like 'oad%'
// -- Here --------------^
0 голосов
/ 08 декабря 2018

Причина сбоя вашей версии в том, что 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);

Это возвращаетрезультат в виде (до) трех строк.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...