Требуется помощь в запросах - агрегаты и множественные объединения - PullRequest
2 голосов
/ 27 июня 2011

У меня есть несколько таблиц, которые используются в моем приложении.Один ведет список продуктов, другой поддерживает комментарии к этим элементам, другой содержит звездные рейтинги этих элементов, а последний покупает эти элементы.Мои таблицы выглядят примерно так:

tbl_item:
---------
id      INT (primary key)
name    VARCHAR (product name)

tbl_comment:
------------
id          INT (primary key)
item_id     INT (foregin key -> tbl_item.id)
commenttext VARCHAR

tbl_rating:
-----------
id          INT (primary key)
item_id     INT (foreign key -> tbl_item.id)
rating      DOUBLE

tbl_purchases:
--------------
id          INT (primary key)
item_id     INT (foreign key -> tbl_item.id)

Я хотел бы выполнить запрос, который возвращает следующее:

* The design ID
* The average rating
* The number of comments
* The number of purchases

У меня было что-то похожее на это, но оно возвращает неверные данные:

SELECT  d.id ,
        COUNT(tbl_purchases.id) AS purchase_count, 
        COUNT(tbl_comment.id) AS comment_count,
        AVG(tbl_rating.rating) AS item_rating,
    FROM tbl_item d
    LEFT JOIN tbl_purchases ON tbl_purchases.item_id = d.id
    LEFT JOIN tbl_comment ON tbl_comment.item_id = d.id
    LEFT JOIN tbl_rating ON tbl_rating.id = d.id
    GROUP BY d.id;

Я обнаружил, что мои столбцы COUNT () возвращают одинаковое значение для обоих столбцов, что, безусловно, неверно.Очевидно, что я делаю что-то не так в своих объединениях или в GROUP BY, но я не совсем уверен, что.Я парень по Java, а не SQL, поэтому я не уверен, что не так в этом операторе SELECT.

Может кто-нибудь помочь мне в создании этого запроса?Есть ли способ выполнить этот агрегированный запрос по нескольким различным таблицам таким образом?Спасибо !!

Ответы [ 3 ]

5 голосов
/ 27 июня 2011

Попробуйте это:

SELECT  d.id ,
        COALESCE(t.purchase_count,0) as purchase_count, 
        COALESCE(c.comment_count,0) as comment_count,
        r.item_rating,
    FROM tbl_item d
    LEFT JOIN (SELECT item_id, COUNT(1) as purchase_count from tbl_purchases group by item_id) as t on t.item_id = d.id
    LEFT JOIN (SELECT item_id, COUNT(1) as comment_count from tbl_comment group by item_id) as c ON c.item_id = d.id
    LEFT JOIN (SELECT item_id, AVG(rating) as item_rating from tbl_rating group by item_id) as r ON r.item_id = d.id;
1 голос
/ 27 июня 2011

Использование count(distinct(tbl_purchases.id)) должно решить вашу проблему без более сложных (но также и правильных) запросов, предложенных другими.

0 голосов
/ 27 июня 2011

Это будет зависеть в некоторой степени от того, какую базу данных вы используете, но это не работает в PostgreSQL:

    SELECT d.id , p.count, c.count, AVG(I.rating)
      FROM tbl_item d
      JOIN ( SELECT count(id), item_id as id from tbl_purchases ) as P
     USING (id)
      JOIN ( SELECT count(id), item_id as id from tbl_comment ) as C
     USING (id)
 LEFT JOIN tbl_rating as I
        ON tbl_rating.id = d.id
  GROUP BY d.id
;
...