Подсчитать для всех значений enum в PostgreSQL - PullRequest
0 голосов
/ 27 декабря 2018

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

id: INT NOT NULL
face: face_type

face_type - это тип ENUM со следующими значениями: 'square', 'round' и 'triangle'.

И у меня есть еще одна таблица с именем houses, которая имеет следующие столбцы:

id: INT NOT NULL
user_id: INT NOT NULL

Теперь я хочу сгруппировать все дома по разным типам типов лица.,Итак, что у меня есть, так это:

SELECT users.face_type, COUNT(*)
FROM users
LEFT JOIN houses ON houses.user_id = users.id
GROUP BY users.face_type

Проблема в том, что я также хочу получить строки для face_type, которых нет ни у одного из пользователей, а также результат для NULL face_type.Так, например, если у меня есть следующие данные:

users (id, face_type)

1, 'round'
2, 'triangle'

houses (id, user_id)
1, 1
2, 1
3, 2

Я ожидаю, что результат будет:

face_type, count
'round'          2
'triangle'       1
'square'         0
null             0

Я знаю, как получить все потенциальные значения face_type ENUM, выполнив:

SELECT unnest(enum_range(NULL::face_type)) AS face_types;

Но я не знаю, как использовать это для подсчета всех потенциальных типов лиц в совокупности, а также для расчета для типов лиц NULL.

Ответы [ 3 ]

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

до СЧЕТА (дома. *)

SELECT face_type.type, COUNT(houses.*)
FROM (SELECT unnest(enum_range(NULL::face_type))) AS face_type(type)
FULL JOIN users ON users.face_type=face_type.type
LEFT JOIN houses ON houses.user_id = users.id
GROUP BY face_type.type
0 голосов
/ 27 декабря 2018

A LEFT JOIN начиная с ENUM и заканчивая users и houses, позволит вам восстановить итоговые значения для каждого перечисленного значения.Чтобы также отобразить NULL типы лиц, вы можете использовать запрос UNION.

SELECT 
    ft.face_type,
    COUNT(ho.user_id) as cnt
FROM 
    (SELECT unnest(enum_range(NULL::face_type)) AS face_types) ft
    LEFT JOIN users us ON us.face_type = ft.fact_type
    LEFT JOIN houses ho ON ho.user_id = us.id
GROUP BY ft.face_type
UNION
SELECT
    null,
    COUNT(ho.user_id)
FROM houses ho
INNER JOIN users us ON ho.user_id = us.id AND us.face_type IS NULL
ORDER BY cnt desc
0 голосов
/ 27 декабря 2018

Вы можете использовать LEFT JOIN:

SELECT ft.face_type, COUNT(h.user_id)
FROM (SELECT unnest(enum_range(NULL::face_type)) AS face_types
     ) ft LEFT JOIN
     users u
     ON u.face_type = ft.face_type LEFT JOIN
     houses h
     ON h.user_id = u.id
GROUP BY ft.face_type;

Чтобы получить NULL, просто используйте UNION ALL:

SELECT ft.face_type, COUNT(h.user_id)
FROM (SELECT unnest(enum_range(NULL::face_type)) AS face_types
      UNION ALL
      SELECT NULL
     ) ft LEFT JOIN
     users u
     ON u.face_type = ft.face_type LEFT JOIN
     houses h
     ON h.user_id = u.id
GROUP BY ft.face_type;

Конечно, = будет не каждыйматч.Если это возможно, то вы хотите изменить условие JOIN на u.face_type is not distinct from ft.face_type.

...