PostgreSQL: подсчет количества столбцов в строке, содержащих значение - PullRequest
0 голосов
/ 02 мая 2018

Допустим, у меня есть таблица со следующими столбцами:

Id

Col1

Col2

Col3

COL4

. .

* Обратите внимание, что у меня есть 50 из этих столбцов ('col1' ... 'col50')

Для каждой строки я хочу подсчитать количество столбцов, начинающихся с 'col' (например, col1, col2 и т. Д.), Которые также содержат определенное целое значение (например, 0).

Так что, если мои данные были:

Id, Col1, Col2, Col3, Col4
0, 0, 1, 2, 1
1, 1, 2, 0, 1
2, 1, 0, 5, 0
3, 0, 0, 0, 4

Мой результат будет:

Id, Count
0, 1
2, 1
2, 2
3, 3

Очевидно, что это нужно масштабировать до 50 столбцов, поэтому я не хочу жестко кодировать имена столбцов (мне нужно, чтобы они были динамическими / циклическими). Я также повторю это с другими значениями, которые я ищу, суть проблемы может быть упрощена до приведенного выше результата.

Я не был уверен, как это сделать. Я подумал о функции, которая принимает имя столбца, значение поиска и счетчик, а затем возвращает итоговую и текущую позицию счетчика или что-то в этом роде. Я должен был бы сделать цикл WHILE для вызова функции, пока не будет достигнут счетчик конца.

Цель состоит в том, чтобы заменить что-то, что работает, но вызывает боль в глазу и не подлежит повторному использованию (с 50 столбцами):

Случай col1, когда 0, затем 1, иначе 0 end + регистр, col col1, когда 0, затем 1, иначе 0 end ...

Ответы [ 3 ]

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

Если вы заранее знаете имена столбцов, вы можете создать массив, развернуть и агрегировать, чтобы получить количество нулей в строке. Пример:

WITH t (Id, Col1, Col2, Col3, Col4) AS (
VALUES
(0, 0, 1, 2, 1),
(1, 1, 2, 0, 1),
(2, 1, 0, 5, 0),
(3, 0, 0, 0, 4)
)
, unnested AS (
SELECT id, (UNNEST(ARRAY[Col1, Col2, Col3, Col4]) = 0)::INT is_zero
FROM t
)
SELECT id, SUM(is_zero) zeros
FROM unnested
GROUP BY 1

В противном случае используйте функции json для изменения формы таблицы, фильтрации по имени столбца (ключу) и значению, а также по совокупности.

WITH t (Id, Col1, Col2, Col3, Col4) AS (
VALUES
(0, 0, 1, 2, 1),
(1, 1, 2, 0, 1),
(2, 1, 0, 5, 0),
(3, 0, 0, 0, 4)
)
SELECT id, COUNT(*)
FROM t, JSON_EACH(ROW_TO_JSON(t)) kv
WHERE kv.key ~ 'col\d+' 
  AND (kv.value::TEXT)::INT = 0
GROUP BY 1
0 голосов
/ 02 мая 2018
with t(id, col1, col2, col3, col4) as (values
  (0,0,1,2,1),
  (3,0,0,0,4))
select * from t cross join lateral (
  select count(*) as cnt
  from json_each_text(to_json(t))
  where key like 'col%' and value = '0') as j;

Демо от lad2925 (c)

Подробнее о функциях JSON.

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

Вы можете использовать что-то вроде PIVOT:

SELECT Id, cnt
FROM tab
JOIN LATERAL ( SELECT COUNT(*) AS cnt_0
               FROM (VALUES(col1),(col2),(col3),(col4)) s(c)
               WHERE s.c=0) AS sub ON true
ORDER BY id;

Демоверсия DBFiddle

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