2016-12-07 13 views
0

私は、特定のロボットを攻撃するためにチームを構成できるすべてのrobot_partnersを表示するクエリを作成しようとしています。 Database Graph複数の条件を持つMySQLの複数の結合と他の行に基づく行の無視

は、したがって、上記の画像を与え、

ケース1:私はそれを見ることができるようにする必要があり、 クリスウォール-E、クリスとウォーリー対象R2D2を制御し、マイクはベンダーを制御していること、およびマイクとBenderはR2D2をターゲットにしており、Wall-EとBenderはパートナーです。これは、KrisとMikeがR2D2を攻撃するのに良いチームメイトであることを示しています。

ケース2:また、 クリスはWall-E、KrisおよびWall-EターゲットGlaDOSを制御し、BenderはGlaDOSをターゲットにし、BenderはWall-Eのパートナーであることを確認する必要があります。この場合、Benderをコントロールし、GlaDOSをターゲットにする人はいません。つまり、GlaDOSを私と一緒にターゲットにするBenderをコントロールする人を見つけることが良いことを意味します。

ケース3:私も見ることができるようにする必要があります。 クリスはWall-E、Kris、Wall-EターゲットRosieを制御します。 Wall-EとBenderはパートナーですが、BenderはRosieをターゲットにしていません。

私は、Wall-EがOptimus Primeをターゲットにしているということは気にしません。なぜなら、KrisはOptimus Primeをターゲットにしていないからです。

この長い間、私はこのクエリを書いているので、テーブルにINSERT SELECTを実行して、そのテーブルから読み込んだ後にアプリケーションを少しだけクリーンアップさせることができます結果はユーザーに表示されます。私は最後の少しそれを得るために助けを必要とするので、アプリケーションはその結果のフォーマット以外に何もする必要はありません。それが今立っているように、これは私のクエリで

SELECT DISTINCT pt.person_id AS person_1, rt.robot_1 AS robot_1, rt.robot_2 AS target, rp.robot_2 AS robot_2, IFNULL(pt2.person_id, 0) AS person_2 
FROM robot_partners AS rp 
JOIN robot_targets AS rt ON (rp.robot_1 = rt.robot_1) 
LEFT JOIN robot_targets AS rt2 ON (rt.robot_2 = rt2.robot_2 And rp.robot_2 = rt2.robot_1) 
JOIN people AS p ON (p.robot_id = rt.robot_1) 
JOIN person_targets AS pt ON (p.person_id = pt.person_id And pt.robot_id = rt.robot_2) 
LEFT JOIN people AS p2 ON (rt2.robot_1 = p2.robot_id) 
LEFT JOIN person_targets AS pt2 ON (p2.person_id = pt2.person_id And rt2.robot_2 = pt2.robot_id) 
ORDER BY pt.person_id, rt.robot_1, rt.robot_2, rp.robot_2; 

このクエリは、このような出力を生成し、

それは私が把握カント重複の束を削除するにはDISTINCTに依存している
|person_1 | robot_1 | target | robot_2 | person_2 | 
| 1  | 1 | 3 |  2 | 0  | 
| 1  | 1 | 3 |  2 | 2  | 
| 1  | 1 | 3 |  11 | 0  | 
| 1  | 1 | 4 |  2 | 3  | 
| 1  | 1 | 4 |  2 | 0  | 
| 1  | 1 | 4 |  11 | 0  | 
| 1  | 1 | 5 |  2 | 3  | 
| 1  | 1 | 5 |  2 | 4  | 
| 1  | 1 | 5 |  2 | 0  | 
| 1  | 1 | 5 |  11 | 0  | 
| 1  | 1 | 6 |  2 | 0  | 
| 1  | 1 | 6 |  11 | 0  | 
| 1  | 1 | 7 |  2 | 0  | 
| 1  | 1 | 7 |  11 | 0  | 
| 1  | 1 | 8 |  2 | 0  | 
| 1  | 1 | 8 |  11 | 0  | 
| 1  | 1 | 9 |  2 | 0  | 
| 1  | 1 | 9 |  11 | 0  | 
| 1  | 1 | 12 |  2 | 0  | 
| 1  | 1 | 12 |  11 | 5  | 
| 2  | 2 | 3 |  1 | 1  | 
| 3  | 2 | 4 |  1 | 1  | 
| 4  | 2 | 5 |  1 | 1  | 
| 5  | 11 | 12 |  1 | 1  | 

クエリを並べ替えることによって削除する方法。また、そのポイントまでの接続がまったく同じストリームのperson_2 IDを持つ行がある場合は、0 person_2の行も戻します。

例:

|person_1 | robot_1 | target | robot_2 | person_2 | 
| 1  | 1 | 5 |  2 | 4  | 
| 1  | 1 | 5 |  2 | 0  | 
PERSON_2 = 4の行があるので、私はPERSON_2 = 0の行を気にしないこの場合

、それらが同一の経路を有する(1,1,5、 2、X)。このような状況が発生したときので

私はその人3と4が接続されてい見ることができるようにする必要があり

|person_1 | robot_1 | target | robot_2 | person_2 | 
| 1  | 1 | 5 |  2 | 3  | 
| 1  | 1 | 5 |  2 | 4  | 
| 1  | 1 | 5 |  2 | 0  | 

、それを取り除くためにDESC/GROUP BY BYサブクエリのORDERを使用しカントとGROUP BYを使用してこの情報を削除します。

しかし、私はケース2が適用されるときを知る必要があるため、person_2 = 0のすべての行を無視することはできません。

person_2がNULLから0に変換される理由は、このデータが格納されるテーブルが5つの列すべてを含む主キーを持ち、PKがNULLを持つことができないためです。また、INSERT INTO SELECTを実行すると、ユニークキーにすることもできません。NULL!= NULLなので重複行が継続的に追加されます。また、5つの列にはそれぞれ、それぞれの表に対する外部キー制約があります。私が人のテーブルにダミーの人0を持っているので、0の理由が働いています。

だから私の理想的な出力は、これらの3行で

|person_1 | robot_1 | target | robot_2 | person_2 | 
| 1  | 1 | 3 |  2 | 2  | 
| 1  | 1 | 3 |  11 | 0  | 
| 1  | 1 | 4 |  2 | 3  | 
| 1  | 1 | 4 |  11 | 0  | 
| 1  | 1 | 5 |  2 | 4  | 
| 1  | 1 | 5 |  2 | 3  | 
| 1  | 1 | 5 |  11 | 0  | 
| 1  | 1 | 6 |  2 | 0  | 
| 1  | 1 | 6 |  11 | 0  | 
| 1  | 1 | 7 |  2 | 0  | 
| 1  | 1 | 7 |  11 | 0  | 
| 1  | 1 | 8 |  2 | 0  | 
| 1  | 1 | 8 |  11 | 0  | 
| 1  | 1 | 9 |  2 | 0  | 
| 1  | 1 | 9 |  11 | 0  | 
| 1  | 1 | 12 |  2 | 0  | 
| 1  | 1 | 12 |  11 | 5  | 
| 2  | 2 | 3 |  1 | 1  | 
| 3  | 2 | 4 |  1 | 1  | 
| 4  | 2 | 5 |  1 | 1  | 
| 5  | 11 | 12 |  1 | 1  | 

は結果から削除された、このようになります。

すべての設定で再生領域。 sqlfiddleに似ています。ここで

http://rextester.com/MQCZX67915

この例で使用されるすべてのテーブルであり、私はまた、rextesterのリンクを提供してきました。このすべてを生成するコードはrextesterリンクにもあります。私はsqlfiddleをやっただろうが、それはクエリを実行することを拒否した。

ありがとうございました。

人物:

+-----------+--------+----------+ 
| person_id | name | robot_id | 
+-----------+--------+----------+ 
|   1 | Kris |  1 | 
|   2 | Mike |  2 | 
|   3 | Sue |  2 | 
|   4 | Dora |  2 | 
|   5 | Walter |  11 | 
+-----------+--------+----------+ 

ロボット:

+----------+----------------+ 
| robot_id |  name  | 
+----------+----------------+ 
|  1 | Wall-E   | 
|  2 | Bender   | 
|  3 | R2D2   | 
|  4 | Data   | 
|  5 | HAL 9000  | 
|  6 | GlaDOS   | 
|  7 | ASIMO   | 
|  8 | The Terminator | 
|  9 | Rosie   | 
|  10 | Optimus Prime | 
|  11 | The Iron Giant | 
|  12 | Clank   | 
+----------+----------------+ 

robot_partners:

+------------------+---------+---------+ 
| robot_partner_id | Robot_1 | Robot_2 | 
+------------------+---------+---------+ 
|    1 |  1 |  2 | 
|    2 |  2 |  1 | 
|    3 |  1 |  11 | 
|    4 |  11 |  1 | 
+------------------+---------+---------+ 

person_targets:

+------------------+-----------+----------+ 
| person_target_id | person_id | robot_id | 
+------------------+-----------+----------+ 
|    1 |   1 |  3 | 
|    2 |   1 |  4 | 
|    3 |   1 |  5 | 
|    4 |   1 |  6 | 
|    5 |   1 |  7 | 
|    6 |   1 |  8 | 
|    7 |   1 |  9 | 
|    8 |   1 |  12 | 
|    9 |   2 |  3 | 
|    10 |   3 |  4 | 
|    11 |   4 |  5 | 
|    12 |   5 |  12 | 
|    13 |   3 |  5 | 
+------------------+-----------+----------+ 

robot_targets:

+-----------------+---------+---------+ 
| robot_target_id | Robot_1 | Robot_2 | 
+-----------------+---------+---------+ 
|    1 |  1 |  3 | 
|    2 |  1 |  4 | 
|    3 |  1 |  5 | 
|    4 |  1 |  6 | 
|    5 |  1 |  7 | 
|    6 |  1 |  8 | 
|    7 |  1 |  9 | 
|    8 |  1 |  10 | 
|    9 |  1 |  12 | 
|    10 |  2 |  3 | 
|    11 |  2 |  4 | 
|    12 |  2 |  5 | 
|    13 |  2 |  6 | 
|    14 |  2 |  7 | 
|    15 |  2 |  8 | 
|    16 |  11 |  12 | 
+-----------------+---------+---------+ 
+0

あなたの理想的な結果では、3行(2ではなく)を削除できません:1-1-3-2-0? – Alan

+0

@Alanあなたは正しい、修正されています。ありがとう。 – NarayanJr

+0

よろしいですか。私は少し答えを修正しました。もともと私は職場から答えて、rextesterコードにアクセスできませんでした。今すぐテストし、2つの構文エラーが見つかりました。今は良いはずです。 – Alan

答えて

1

はTHSTが持っているか、人の2を持っていないのいずれかの全ての組合せと組み合わせて人2を持っているすべての組み合わせのUNIONを行いますが、いずれにしても最初の4つの部品ではありません最初のリストに表示されます。 CONCAT_WSは、1 + 23と12 + 3の差異を区別するために必要です。両方とも123に連結すると、1〜23と12〜3になります。

(SELECT DISTINCT pt.person_id AS person_1, rt.robot_1 AS robot_1, rt.robot_2 AS target, rp.robot_2 AS robot_2, pt2.person_id AS person_2 

FROM robot_partners AS rp 

JOIN robot_targets AS rt ON (rp.robot_1 = rt.robot_1) 

JOIN robot_targets AS rt2 ON (rt.robot_2 = rt2.robot_2 And rp.robot_2 = rt2.robot_1) 

JOIN people AS p ON (p.robot_id = rt.robot_1) 

JOIN person_targets AS pt ON (p.person_id = pt.person_id And pt.robot_id = rt.robot_2) 

JOIN people AS p2 ON (rt2.robot_1 = p2.robot_id) 

JOIN person_targets AS pt2 ON (p2.person_id = pt2.person_id And rt2.robot_2 = pt2.robot_id)) 

UNION 

(SELECT DISTINCT pt.person_id AS person_1, rt.robot_1 AS robot_1, rt.robot_2 AS target, rp.robot_2 AS robot_2, IFNULL(pt2.person_id, 0) AS person_2 

FROM robot_partners AS rp 

JOIN robot_targets AS rt ON (rp.robot_1 = rt.robot_1) 

LEFT JOIN robot_targets AS rt2 ON (rt.robot_2 = rt2.robot_2 And rp.robot_2 = rt2.robot_1) 

JOIN people AS p ON (p.robot_id = rt.robot_1) 

JOIN person_targets AS pt ON (p.person_id = pt.person_id And pt.robot_id = rt.robot_2) 

LEFT JOIN people AS p2 ON (rt2.robot_1 = p2.robot_id) 

LEFT JOIN person_targets AS pt2 ON (p2.person_id = pt2.person_id And rt2.robot_2 = pt2.robot_id) 

WHERE CONCAT_WS('~',pt.person_id, rt.robot_1, rt.robot_2, rp.robot_2) 

    NOT IN 

     (SELECT DISTINCT CONCAT_WS('~',pt.person_id, rt.robot_1, rt.robot_2, rp.robot_2) 

     FROM robot_partners AS rp 

     JOIN robot_targets AS rt ON (rp.robot_1 = rt.robot_1) 

     JOIN robot_targets AS rt2 ON (rt.robot_2 = rt2.robot_2 And rp.robot_2 = rt2.robot_1) 

     JOIN people AS p ON (p.robot_id = rt.robot_1) 

     JOIN person_targets AS pt ON (p.person_id = pt.person_id And pt.robot_id = rt.robot_2) 

     JOIN people AS p2 ON (rt2.robot_1 = p2.robot_id) 

     JOIN person_targets AS pt2 ON (p2.person_id = pt2.person_id And rt2.robot_2 = pt2.robot_id)) 

) 

ORDER BY person_1, robot_1, target, robot_2; 
+0

うわー、私は私の試みでそれに近いところにいませんでした。私はクエリが実際にどのくらい速く実行されるかに驚いています。それがどれだけうまくスケールするかについてのアイデア?私はそれがインデックスを使用できるとは思っていないので、それがCONCAT NOT INの問題に繋がると私は思うだろう。助けをありがとう – NarayanJr

+0

ええ、すべてのテーブルが巨大になった場合、それは遅くなるかもしれません。しかし、あなたは**誰のためにも**誰とでも誰ができるのかという疑問を尋ねていることに気づいてください。もしあなたが1人のプレイヤーの視点からそれを実行していたなら、3つの場所に 'WHERE p.person_id = 5'を追加すると、それはたくさんの連結を行わないようにします。 – Alan

関連する問題