2

A、B、C の 3 つの (MYSQL) テーブルがあります。

私がやりたいことは次のようなものです:

SELECT * FROM a
LEFT JOIN b ON b.a_id = a.id
LEFT JOIN c on c.a_id = a.id
WHERE a.id = 1;

B テーブルに B.a_id = 1 のエントリが 4 つあります。

B.id | b.a_id
1    | 1
2    | 1
3    | 1
4    | 1

Cテーブルにもそのようなエントリが2つあります

C.id | C.a_id
10   | 1
11   | 1

8 つの結果が返されます。

C.id | B.id
10    | 1
10    | 2
10    | 3
10    | 4
11    | 1
11    | 2
11    | 3
11    | 4

同じ C オブジェクトと B オブジェクトを繰り返さずに結果を取得し、このようなものを返す方法はありますか?

C.id | B.id
10    | 1
11    | 2
NULL  | 3
NULL  | 4

つまり、「A=1 にマップされるものはすべて与えてください。ただし、同じ C または B を 2 回繰り返さないでください」と言いたいのです。私の実際のデータでは、10 個近くのテーブルを結合しており、結合されたすべてのテーブルのすべての順列により、結果はしばしば数千行の長さになります。

ここに同様の質問がありますConnecting Multiple Tables in SQL while Limiting Exponential Resultsですが、可能な限り内部選択を避けたいです。これは、あるべきデータベースの十分に一般的な使用法だと思います

4

3 に答える 3

1

必要なのは単純な SQL ではありません。また、リレーショナル データベースで簡単に実行できると期待するべきではありません。

すべての値を 1 つの列に入れ、別の列で値の由来を指定することをお勧めします。これにより、大きなunion allタイプのクエリが生成されます。

select 'b' as which, b.id
from a join b on b.a_id = a.id and a.id = 1
union all
select 'c', c.id
from a join c on c_aid = b.id and a.id = 1
. . .

結果は、まさにあなたが望むものではありません。

本当にデータを別々の列に入れたい場合は、トリックを使用して各行に行番号を割り当てる必要があります。次に、行番号で結果を集計できます。このようなもの:

select rn,
       MAX(case when which = 'b' then id end) as b,
       MAX(case when which = 'b' then id end) as c
from (select 'b' as which, b.id, @rn := @rn + 1 as rn
      from a join b on b.a_id = a.id and a.id = 1 cross join (select @rn := 0) const
      union all
      select 'c', c.id, @rn := @rn + 1 as rn
      from a join c on c_aid = b.id and a.id = 1 cross join (select @rn := 0) const
     ) t
group by rn
于 2013-05-07T15:59:23.933 に答える
1

これは、SQL を使用してデータを取得するための基本です。SELECT句で要求されたプロジェクションで定義されているように、それぞれが同じ列を持つ完全な行でデータを取得します。SQL でこのような問題に遭遇したときはいつでも、次の 3 つの質問を自問することが役に立ちました。

  1. 必要な結果行はどのようになりますか? つまり、それらにはどのような列がありますか?
  2. データベースは各列に入力する方法をどのように知るのでしょうか?
  3. データベースはどの行を返すかをどのように認識しますか?

特定のシナリオについてこれらの質問に答えると、一歩下がって、特定のJOINまたはGROUP BYが問題を引き起こしている理由を理解するのに役立ちました。一般に、それはデータベースに概念がないことをデータベースに要求するためです。

あなたの場合、データの行を取得すると、データベースがテーブル B から複数の行を取得し、テーブル C から複数の行を取得する方法はありません。これらの行のデカルト積は得られません。重複したデータが必要ない場合は、SELECTs を個別に発行する必要があります。

上記の質問に対する答えとして、次のように表現します。各行には、テーブル A のすべてのデータが含まれます。テーブル B と C の複数の行を任意の数の列に収める方法はないため、うまくいきません。すべての行が同じ長さであるため、B と C から短い行のデータを返す方法はありません。B の各行と C の各行に対して完全な行を返す必要があります。これにより、説明したシナリオが正確に得られます。

于 2013-05-07T16:00:49.527 に答える
0

誰かがそれを使用するかもしれませんが、簡単に思えます....

次のことを試していただけますか...

左関節の代わりに

SELECT * FROM a
LEFT JOIN b ON b.a_id = a.id
LEFT JOIN c on c.a_id = a.id
WHERE a.id = 1;

次の内部結合を使用します

SELECT * FROM a
INNER JOIN b ON b.a_id = a.id
INNER JOIN c on c.a_id = a.id
WHERE a.id = 1;

それはうまくいくはずです...私は思う..

于 2013-08-14T15:33:35.850 に答える