Запрос комбинаций JSON возвращает нечетные результаты

Это продолжение question. Кажется, я столкнулся с краевым случаем, и я не понимаю, почему я получаю неправильные результаты. Используя данные из связанного вопроса, Я могу сгруппировать их в комбинации, которые используют один и тот же альбом, src и background.

Например, используя эти данные:

CREATE TABLE reports (rep_id int primary key, data json);
INSERT INTO reports (rep_id, data)
VALUES 
  (1, '{"objects":[{"album": 1, "src":"fooA.png", "pos": "top"},   {"album": 2, "src":"barB.png", "pos": "top"}],   "background":"background.png"}'),
  (2, '{"objects":[{"album": 1, "src":"fooA.png", "pos": "top"},   {"album": 2, "src":"barC.png", "pos": "top"}],   "background":"background.png"}'),
  (3, '{"objects":[{"album": 1, "src":"fooA.png", "pos": "middle"},{"album": 2, "src":"barB.png", "pos": "middle"}],"background":"background.png"}'),
  (4, '{"objects":[{"album": 1, "src":"fooA.png", "pos": "top"},   {"album": 3, "src":"barB.png", "pos": "top"}],   "background":"backgroundA.png"}')
;

и это запрос:

SELECT distinct array_agg(distinct r.rep_id) AS ids, count(*) AS ct
FROM   reports r
  , json_array_elements(r.data->'objects') o
GROUP  BY r.data->>'background'
   , o->>'album'
   , o->>'src'
ORDER  BY count(*) DESC
LIMIT  5;

Я получаю эти результаты, которые неверны:

  ids    | ct 
---------+----
 {1,2,3} |  3
 {1,3}   |  2
 {2}     |  1
 {4}     |  1

Я хочу, чтобы это

  ids    | ct 
---------+----
 {1,3}   |  2
 {2}     |  1
 {4}     |  1

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

Edit Мне пришлось изменить свой вопрос. Оказывается, у моих образцов данных была ошибка, и я не получал правильных результатов. Поэтому я ищу запрос, который работает, если это возможно.

Ответ 1

Добрый человек из IRC-канала Postgresql помог найти ответ и обработать правильный запрос. Кредит - это его, а не мой.

Он помог понять, что альбомы и srcs должны быть добавлены в массивы для сравнения. Например:

SELECT array_agg(rep_id), count(*) AS ct
FROM (SELECT rep_id, 
             data->>'background' as background, 
             array_agg(o->>'album' order by o->>'album') as albums, 
             array_agg(o->>'src' order by o->>'album') as srcs  
           FROM reports r, 
           json_array_elements(r.data->'objects') o 
           GROUP BY rep_id) s 
GROUP BY background, albums, srcs
ORDER BY count(*) DESC
LIMIT 5;

Я не знаю, это лучший способ сделать это, но он работает. Предложения приветствуются.

Ответ 2

Прежде всего, у вас есть опечатка, измените 'scr' на 'src'. Но ваш запрос правильный, просто взгляните на свой запрос без группировки:

select
     r.rep_id, r.data->>'background' as background, o->>'album' as album, o->>'src' as src
from reports r, json_array_elements(r.data->'objects') o;

------------------------------------------------------------
REP_ID  BACKGROUND      ALBUM   SRC
1       background.png      1   fooA.png
1       background.png      2   barB.png
2       background.png      2   barB.png
2       background.png      2   barB.png

Ответ 3

Если вы посчитаете отличным от rep_id, вы получите количество строк, в которых произошла уникальная комбинация.

SELECT distinct array_agg(distinct r.rep_id) AS ids, count(distinct r.rep_id) AS ct, array[r.data->>'background', o->>'album', o->>'src'] as combination
FROM   reports r
  , json_array_elements(r.data->'objects') o
GROUP  BY r.data->>'background'
   , o->>'album'
   , o->>'src'
ORDER  BY 2 DESC

Результат для первого набора данных:

ids     ct  combination
{1,2,3} 3   {background.png,1,fooA.png}
{1,3}   2   {background.png,2,barB.png}
{2}     1   {background.png,2,barC.png}
{4}     1   {backgroundA.png,1,fooA.png}
{4}     1   {backgroundA.png,3,barB.png}

Повторить второй набор данных:

ids     ct  combination
{1,2}   2   {background.png,2,barB.png}
{1}     1   {background.png,1,fooA.png}