Таблица соединения SQL как данные JSON - PullRequest
0 голосов
/ 24 февраля 2019

Я пытаюсь присоединить отзывы и лайки к продуктам, но, по какой-то причине, вывод столбца «отзывы» дублируется длиной другой внешней таблицы, лайков, длина вывода «отзывов» равна

amount of likes * amount of reviews

Понятия не имею, почему это происходит

Мой желаемый вывод - столбец «reviews» содержит массив данных JSON, так что один массив равен одной строке связаннойОтзыв

Продукты

Title        Image
----------------------
Photo        photo.jpg
Book         book.jpg
Table        table.jpg

Пользователи

Username
--------
Admin
John
Jane

Нравится продукт

product_id    user_id
---------------------
1             1
1             2
2             1
2             3

Отзывы о товаре

product_id    user_id    review
-------------------------------------
1             1          Great Product!
1             2          Looks Great
2             1          Could be better

Это запрос

SELECT "products".*, 
array_to_json(array_agg("product_review".*)) as reviews,
EXISTS(SELECT * FROM product_like lk
JOIN users u ON u.id = "lk"."user_id" WHERE u.id = 4
AND "lk"."product_id" = products.id) AS liked,
COUNT("product_like"."product_id") AS totalLikes from "products"
LEFT JOIN "product_review" on "product_review"."product_id" = "products"."id" 
LEFT JOIN "product_like" on "product_like"."product_id" = "products"."id" 
group by "products"."id"

Запрос на создание схемы и вставку данных

CREATE TABLE products
    (id SERIAL, title varchar(50), image varchar(50), PRIMARY KEY(id))
;

CREATE TABLE users
    (id SERIAL, username varchar(50), PRIMARY KEY(id))
;

INSERT INTO products
    (title,image)
VALUES
    ('Photo', 'photo.jpg'),    
    ('Book', 'book.jpg'),
    ('Table', 'table.jpg')
;

INSERT INTO users
    (username)
VALUES
    ('Admin'),    
    ('John'),
    ('Jane')
;






CREATE TABLE product_review
    (id SERIAL, product_id int NOT NULL, user_id int NOT NULL, review varchar(50), PRIMARY KEY(id), FOREIGN KEY (product_id) references products, FOREIGN KEY (user_id) references users)
;

INSERT INTO product_review
    (product_id, user_id, review)
VALUES
    (1, 1, 'Great Product!'),
    (1, 2, 'Looks Great'),
    (2, 1, 'Could be better')
;



CREATE TABLE product_like
    (id SERIAL, product_id int NOT NULL, user_id int NOT NULL, PRIMARY KEY(id), FOREIGN KEY (product_id) references products, FOREIGN KEY (user_id) references users)
;

INSERT INTO product_like
    (product_id, user_id)
VALUES
    (1, 1),
    (1, 2),
    (2, 1),
    (2, 3)

скрипка со схемой и запросом: http://sqlfiddle.com/#!15/dff2c/1

Заранее спасибо

1 Ответ

0 голосов
/ 24 февраля 2019

Причина, по которой вы получаете несколько результатов, заключается в том, что отношения product_id и product_review и product_like приводят к дублированию строк перед агрегацией.Чтобы обойти это, вам нужно выполнить агрегирование этих таблиц в подзапросах и вместо этого объединить производные таблицы:

SELECT "products".*, 
"pr"."reviews",
EXISTS(SELECT * FROM product_like lk
JOIN users u ON u.id = "lk"."user_id" WHERE u.id = 4
AND "lk"."product_id" = products.id) AS liked,
COALESCE("pl"."totalLikes", 0) AS totalLikes
FROM "products"
LEFT JOIN (SELECT product_id, array_to_json(array_agg("product_review".*)) AS reviews
           FROM "product_review"
           GROUP BY product_id) "pr" on "pr"."product_id" = "products"."id" 
LEFT JOIN (SELECT product_id, COUNT(*) AS "totalLikes"
           FROM "product_like"
           GROUP BY product_id) "pl" on "pl"."product_id" = "products"."id" 

Вывод:

id  title   image       reviews                                                                                                                     liked   totallikes
1   Photo   photo.jpg   [{"id":1,"product_id":1,"user_id":1,"review":"Great Product!"},{"id":2,"product_id":1,"user_id":2,"review":"Looks Great"}]  f       2
2   Book    book.jpg    [{"id":3,"product_id":2,"user_id":1,"review":"Could be better"}]                                                            f       2
3   Table   table.jpg                                                                                                                               f       0

Демонстрация на dbfiddle

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