2011-06-27 19 views
2

私のアプリケーションで使用されるいくつかのテーブルがあります。 1つは製品のリストを維持し、もう1つはそれらのアイテムに対するコメントを維持し、別のものはそれらのアイテムの星評価を含み、最後にはそれらのアイテムの購入がある。私はこれに似た何かを持っていたが、それは間違ったデータを返すクエリのヘルプが必要 - 集約と複数の結合

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

を私は次のことを返すクエリを実行したいと思います

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) 

:私のテーブルには、次のようになり

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文で何がうまくいかないのか分かりません。

誰でも私にこのクエリの作成に手を差し伸べることはできますか?このようにいくつかの異なるテーブルでこの集約クエリを実行する方法はありますか?ありがとう!!

+0

最終的な結果セットをカウントしているのでカウントが戻ります(ヌルかどうかは関係ありません)。あなたはテーブルごとに別々のカウントをしたい場合、私はサブクエリを調べることをお勧めします。 – Limey

+0

また、変数を設定し、caseステートメントで各テーブルの合計を手動で追跡することもできます。 – Limey

+0

サブクエリを使用してこれをどのように実行するかの例を教えてください。私が言ったように、私はJavaの男であり、SQLでひどく経験はありません。 – Shadowman

答えて

5

ことは、これを試してみてください:

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; 
+0

私にそれを打つ:) +1 – Randy

+0

@Seth Robertsonの答えを試してみましたが、それはうまくいったのですが、パフォーマンスはひどいものでした。この答えはうまくいった。大きさの速い注文。ありがとう! – Shadowman

+0

大まかには、グループの後ではなく、グループの前に実装するほうがよいでしょう。グループを実行して結合を実行するためにDBが何をしなければならないかについて考えるなら、これが本当である理由を理解するでしょう(私は説明を与えるのに十分なスペースがありません:))。 – Gareth

0

それはあなたが使用しているDBものに多少依存しますが、PostgreSQLではこのouttaの仕事でしょう:

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 
; 
1

count(distinct(tbl_purchases.id))を使用して、よりせずに、あなたの問題を解決する必要があります複雑なクエリ(ただし、正確なクエリ)も提供しています。

+0

それは魅力的に機能しました!ありがとう! – Shadowman

+0

私はこのクエリを実行し、それは素晴らしい動作します。しかし、私はパフォーマンスが恐ろしいことに気づいた。他の回答があれば、より高速なクエリが得られるでしょうか?より良いパフォーマンスを得る方法はありますか? – Shadowman

関連する問題