0

ユーザー テーブル:

  • user_id (ユーザーごとに異なる)
  • source_id (ユーザーは同じソースを持っている可能性があります)

ルール テーブル:

  • white_rules
  • black_rules
  • 一般的なルール

これらのテーブルはすべて同じように見え、次のものがあります。

  • victim_id (users テーブルの user_id に関連付けられます)。
  • rule_id (ここでは重要ではない別のテーブルに関連付けられています)

必要なのは、source_id ごとのタイプ (白、黒、一般) ごとの合計ルールの量を抽出することです。

例:

  • source_id: 5 ---> 合計 70 個の白ルール、合計 32 個の黒ルール、合計 21 個の一般ルール
  • source_id: 7 ---> 白ルール計2枚、黒ルール計0枚、一般ルール計4枚

など... users テーブルにリストされているすべての個別のソースに対して。

私が試したのは:

SELECT source_id,
count(w.victim_id) as total_white,
count(b.victim_id) as total_black,
count(g.victim_id) as total_general
from users
LEFT JOIN white_rules as w ON (user_id=w.victim_id)
LEFT JOIN black_rules as b ON (user_id=b.victim_id)
LEFT JOIN general_rules as g ON (user_id=g.victim_id)
where deleted='f' and source is not null
group by source;

しかし、私が得た結果テーブルには、私が期待していたよりも間違った(高い)数値が含まれているため、何か間違ったことをしているに違いありません:)正しい方向のヒンジを高く評価します。

4

1 に答える 1

0

複数の1対多の関係が交差結合を引き起こしているため、サブクエリでカウントを行うか、個別にカウントする必要があります。あなたのデータはわかりませんが、次のシナリオを想像してください。

ユーザー:

User_ID |   Source_ID
--------+--------------
  1     |      1  

ホワイト_ルール

Victim_ID | Rule_ID
----------+-------------
   1      |    1
   1      |    2

Black_Rules

Victim_ID | Rule_ID
----------+-------------
   1      |    3
   1      |    4

あなたが実行する場合

SELECT  Users.User_ID, 
        Users.Source_ID, 
        White_Rules.Rule_ID AS WhiteRuleID, 
        Black_Rules.Rule_ID AS BlackRuleID
FROM    Users
        LEFT JOIN White_Rules
            ON White_Rules.Victim_ID = Users.User_ID
        LEFT JOIN Black_Rules
            ON Black_Rules.Victim_ID = Users.User_ID

と のすべての組み合わせを取得しWhite_Rules.Rule_IDますBlack_Rules.Rule_ID

User_ID | Source_ID | WhiteRuleID | BlackRuleID
--------+-----------+-------------+-------------
  1     |    1      |      1      |      3
  1     |    1      |      2      |      4
  1     |    1      |      1      |      3
  1     |    1      |      2      |      4

したがって、結果を数えると、それぞれ 2 つしかないにもかかわらず、4 つの白のルールと 4 つの黒のルールが返されます。

クエリを次のように変更すると、必要な結果が得られるはずです。

SELECT  Users.Source_ID,
        SUM(COALESCE(w.TotalWhite, 0)) AS TotalWhite,
        SUM(COALESCE(b.TotalBlack, 0)) AS TotalBlack,
        SUM(COALESCE(g.TotalGeneral, 0)) AS TotalGeneral
FROM    Users
        LEFT JOIN
        (   SELECT  Victim_ID, COUNT(*) AS TotalWhite
            FROM    White_Rules
            GROUP BY Victim_ID
        ) w
            ON w.Victim_ID = Users.User_ID
        LEFT JOIN
        (   SELECT  Victim_ID, COUNT(*) AS TotalBlack
            FROM    Black_Rules
            GROUP BY Victim_ID
        ) b
            ON b.Victim_ID = Users.User_ID
        LEFT JOIN
        (   SELECT  Victim_ID, COUNT(*) AS TotalGeneral
            FROM    General_Rules
            GROUP BY Victim_ID
        ) g
            ON g.Victim_ID = Users.User_ID
WHERE   Deleted = 'f'
AND     Source IS NOT NULL
GROUP BY Users.Source_ID

SQL Fiddle の例

別の方法は次のとおりです。

SELECT  Users.Source_ID,
        COUNT(Rules.TotalWhite) AS TotalWhite,
        COUNT(Rules.TotalBlack) AS TotalBlack,
        COUNT(Rules.TotalGeneral) AS TotalGeneral
FROM    Users
        LEFT JOIN
        (   SELECT  Victim_ID, 1 AS TotalWhite, NULL AS TotalBlack, NULL AS TotalGeneral
            FROM    White_Rules
            UNION ALL
            SELECT  Victim_ID, NULL AS TotalWhite, 1 AS TotalBlack, NULL AS TotalGeneral
            FROM    Black_Rules
            UNION ALL
            SELECT  Victim_ID, NULL AS TotalWhite, NULL AS TotalBlack, 1 AS TotalGeneral
            FROM    General_Rules
        ) Rules
            ON Rules.Victim_ID = Users.User_ID
WHERE   Deleted = 'f'
AND     Source IS NOT NULL
GROUP BY Users.Source_ID

SQL Fiddle の例

于 2013-02-27T17:25:16.307 に答える