Ваша таблица предметов имеет 100 строк. Вы присоединяетесь к таблице голосов. Таким образом, вы получаете все голоса за элемент, например, 10 голосов за элемент 1, 5 голосов за элемент 2, 0 голосов за элемент 3, ... Если вы используете внутреннее соединение, вы потеряете 0 голосов за элемент 3, потому что нет проголосуйте за пункт 3 в таблице. Затем каждый голос связан с пользователем. Для элемента 3 нет голосования, поэтому, пока вы создаете результат для элемента 3 без голосов (NULL, который COALESCE
превращается в 0), этот результат является пустым (т. Е. Идентификатор пользователя также, конечно, равен NULL). Это все, что делает внешнее объединение.
Затем вы группируете пользователей и собираете их голоса в массивы. Допустим, пользователь 1 имеет 40 голосов, пользователь 2 имеет 30 голосов, пользователь 3 не имеет голосов, а пользователь 4 имеет 20 голосов. Для этого вы получите три строки результатов (по одной для каждого пользователя в данных): одну для пользователя 1 с массивом из 40 голосов, одну для пользователя 2 с массивом из 30 голосов, одну для пользователя 4 с массивом из 20 голоса.
Вы хотите, чтобы массивы волшебным образом содержали по 100 голосов каждый. Из этого я понимаю, что таблица голосов имеет уникальный ключ для пользователя и элемента, и вы хотите выбрать всех пользователей со значением голоса для каждого элемента - нулевое значение в случае отсутствия записи для голосования.
Для этого чтобы это произошло, вы должны сначала создать все нужные строки: пользователи х элементов. Затем выполните внешнее объединение голосов.
SELECT u.user_id, ARRAY_AGG(COALESCE(v.value, 0) ORDER BY i.item_id)
FROM users u
CROSS JOIN items i
LEFT JOIN votes v ON v.user_id = u.user_id and v.item_id = i.item_id
GROUP BY u.user_id
ORDER BY u.user_id;
Если вы хотите ограничить это для пользователей хотя бы одним голосом, то либо замените FROM users u
на FROM (SELECT DISTINCT user_id FROM votes) u
, либо добавьте HAVING COUNT(v.item_id) > 0
.