SQL: эффективный способ подсчета и группировки результатов по одинаковому значению - PullRequest
3 голосов
/ 14 февраля 2020

У меня есть таблица, которая выглядит следующим образом:

+----+-------+
| id | col2  |
+----+-------+
|  1 | a     |
|  2 | b     |
|  3 | ,b    |
|  4 | c     |
|  5 | d,a   |
|  6 | e,a,b |
+----+-------+

Какой самый эффективный способ запросить ее и вернуть следующее?

+------+----------+
| col1 | count_id |
+------+----------+
| a    |        3 |
| b    |        3 |
| c    |        1 |
| d    |        1 |
| e    |        1 |
+------+----------+

Я думал использовать case when заявлений, но это кажется грязным.

Ответы [ 2 ]

1 голос
/ 14 февраля 2020

Ну, вам может понадобиться таблица символов, содержащая все символы, которые могут появиться во втором столбце. Предполагая, что у вас это есть, вы можете попробовать объединить подход:

WITH letters AS (
    SELECT 'a' AS col1 UNION ALL
    SELECT 'b' UNION ALL
    SELECT 'c' UNION ALL
    ...
    SELECT 'z'
)

SELECT
    t1.col1,
    COUNT(t2.col2) AS count_id
FROM letters t1
LEFT JOIN yourTable t2
    ON ',' || t2.col2 || ',' LIKE '%,' || t1.col1 || ',%'
GROUP BY
    t1.col1
ORDER BY
   t1.col1;

Обратите внимание, что принятый ответ работает, только если в col2 есть все буквы, о которых мы хотим сообщить. Если нет, то в выводе будет отсутствовать информация.

1 голос
/ 14 февраля 2020

В Presto вы можете разбить список с разделителями на массив, а затем развернуть массив. Это дает вам одну запись на элемент в каждом списке. Остальное просто агрегация:

select s.colx, count(*) cnt 
from mytable t
cross join unnest(split(t.col2, ',')) as s(colx)
group by s.colx

Если вы хотите подсчет различных id с (в случае, если в списках с разделителями есть дубликаты):

select s.colx, count(distinct t.id) cnt 
from mytable t
cross join unnest(split(t.col2, ',')) as s(colx)
group by s.colx
...