Подсчет строк SQLite, которые могут совпадать несколько раз в одном запросе - PullRequest
0 голосов
/ 21 мая 2018

У меня есть таблица SQLite, в которой есть столбец, содержащий категории, в которые может попасть каждая строка.Каждая строка имеет уникальный идентификатор, но может относиться к нулю, одной или нескольким категориям, например:

|-------+-------|
| name  | cats  |
|-------+-------|
| xyzzy | a b c |
| plugh | b     |
| quux  |       |
| quuux | a c   |
|-------+-------|

Я хотел бы получить количество элементов в каждой категории.Другими словами, вывод выглядит так:

|------------+-------|
| categories | total |
|------------+-------|
| a          | 2     |
| b          | 2     |
| c          | 2     |
| none       | 1     |
|------------+-------|

Я пытался использовать оператор case так:

select case
    when cats like "%a%" then 'a'
    when cats like "%b%" then 'b'
    when cats like "%c%" then 'c'
    else 'none'
end as categories,
count(*)
from test
group by categories

Но проблема в том, что подсчитывается только каждая строка один раз , поэтому он не может обрабатывать несколько категорий.Вместо этого вы получите следующий вывод:

|------------+-------|
| categories | total |
|------------+-------|
| a          | 2     |
| b          | 1     |
| none       | 1     |
|------------+-------|

Одна из возможностей - использовать столько union операторов, сколько у вас есть категорий:

select case
    when cats like "%a%" then 'a'
end as categories, count(*)
from test
group by categories
union
select case
    when cats like "%b%" then 'b'
end as categories, count(*)
from test
group by categories
union
...

, но это кажется действительно уродливым и противоположнымСУХОЙ.

Есть ли лучший способ?

1 Ответ

0 голосов
/ 21 мая 2018

Исправьте вашу структуру данных!У вас должна быть таблица с одной строкой на name и на category:

create table nameCategories (
    name varchar(255),
    category varchar(255)
);

Тогда ваш запрос будет простым:

select category, count(*)
from namecategories
group by category;

Почему ваша структура данных плохая?Вот несколько причин:

  • Столбец должен содержать одно значение.
  • SQL имеет довольно паршивую строковую функциональность.
  • Запросы SQL для выполнения того, что вы хотите, не могут бытьоптимизирован.
  • SQL имеет отличную структуру данных для хранения списков.Она называется таблица , а не строка .

Имея это в виду, вот один метод грубой силы для выполнения того, что вы хотите:

with categories as (
      select 'a' as category union all
      select 'b' union all
      . . .
     )
select c.category, count(t.category)
from categories c left join
     test t
     on ' ' || t.categories || ' ' like '% ' || c.category || ' %' 
group by c.category;

Если у вас уже есть таблица допустимых категорий, CTE не требуется.

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