2

製品とジャンルの 2 つのテーブルがあります。製品テーブルには、2 つのジャンル (genre_id と Genre_id2) を含む製品に関するすべての情報が含まれています。

Genre テーブルには、製品テーブルのジャンル ID に関連付ける ID を持つすべての可能なジャンル名があります

テーブル製品
--------------
id 商品名 ジャンルID ジャンルID2
--------------------------------------------------
1 製品 1 2
2 製品2 2
3 製品3 1 4
4 製品4 3 4

テーブルのジャンル
-----------
id ジャンル名
--------------------------------------------------
1 ジャンル1
2 ジャンル2
3 ジャンル3
4 ジャンル4

さまざまなジャンルをすべて選択して、そのジャンルの製品がいくつあるかを確認したい

このようなもの

結果
------
ジャンル_idカウント
-----------------------
    1 2
    2 2
    3 1
    4 2

私はこの声明を持っています

SELECT DISTINCT p.genre_id AS genre, g.genre_name,  COUNT(p.genre_id) AS cnt
FROM products AS p
JOIN genre AS g
ON p.genre_id=g.id
GROUP BY genre_id
ORDER BY cnt DESC

しかし、genre_idでのみ機能し、このステートメントにgenre_id2を組み込み、genre_idと一致するカウントを追加して、さまざまなものをリストする方法がわかりません

4

3 に答える 3

3
SELECT  a.ID, COUNT(DISTINCT b.ID) + COUNT(DISTINCT c.ID)
FROM    Genre a
        LEFT JOIN products b
            ON a.ID = b.genre_id
        LEFT JOIN products c
            ON a.ID = c.genre_id2
GROUP BY a.ID

genre_id and genre_ID2警告: 同じ例のレコードがある場合、これは機能しません

5     product5            1            1
于 2013-04-25T00:16:27.407 に答える
2

結合するテーブルがある場合genre、「明白な」解決策は次のようになります。

SELECT genre.id AS genre, COUNT(products.id) AS n
FROM genre
  LEFT JOIN products ON genre.id IN (genre_id, genre_id2)
GROUP BY genre.id

( SQLFiddle デモ)

ただし、そうしなかった場合でも、次を使用してこれを行うことができますUNION

SELECT genre, COUNT(*) as n
FROM
  (SELECT id, genre_id AS genre FROM products
   WHERE genre_id IS NOT NULL
   UNION
   SELECT id, genre_id2 AS genre FROM products
   WHERE genre_id2 IS NOT NULL) AS foo
GROUP BY genre

( SQLFiddle デモ)


編集:このメソッドは、カウントが 0 の行を返しませUNIONん (そしてできませんLEFT JOIN) 。それらが必要ない場合は、LEFT JOINを単にJOIN.


編集 2:適切なインデックス ( と のそれぞれに 1 つgenre_id)genre_id2を使用し、実際のデータ セットのサイズと内容に応じて、従属サブクエリを使用する次のソリューションは、上記のいずれよりも効率的である可能性があります。

SELECT genre.id AS genre,
  (SELECT COUNT(*) FROM products WHERE genre.id = genre_id) +
  (SELECT COUNT(*) FROM products WHERE genre.id = genre_id2) AS n
FROM genre

カウントがゼロの行を削除するには、そのまま貼り付けます

HAVING n > 0

クエリの最後に。( SQLFiddle デモ) これは、実際には、そのような行を除外するための一般的な方法です。

実際のデータが必要になるため、どちらがより効率的であるかを確認するために、JWのソリューションに対してこれをベンチマークしていません。データセットがかなり小さい場合は、どちらの方法でも問題ない場合があります。

(結果は、MySQL がそれらをどれだけうまく最適化するかに大きく依存します。JW のネストされたLEFT JOINs は、単純に実行すると、大きなデータ セットで非常に遅くなる可能性がありますが、MySQL がそれを行わないほどスマートであるかどうかはわかりません。その間、私の従属サブクエリおそらくあまり最適化されませんが、必要なインデックスが存在する限り、単純な実行でもかなり高速になるはずです。)


編集 3:一般に、この問題はテーブルの設計が悪いために発生することに注意してください。この回答などで説明されているように、ジャンクション テーブルを使用するようにスキーマを変更することをお勧めします。

これにより、各製品を任意の数のジャンルに属することができ、次のような単純なクエリを使用して各ジャンルの製品を簡単に数えることができます。

SELECT genre.id AS genre, COUNT(products.id) AS n
FROM genre
  JOIN product_genre ON genre.id   = product_genre.genre
  JOIN products      ON product.id = product_genre.product
GROUP BY genre.id
于 2013-04-25T00:24:38.500 に答える
1

ジャンル_id2で同様のステートメントを作成し、元の結果と結合します

于 2013-04-25T00:19:14.833 に答える