5

私が持っているとしましょうtable1

  id      name
-------------
  1       "one"
  2       "two"
  3       "three"

そしてtable2、最初の外部キーを持つa:

id    tbl1_fk    option   value
-------------------------------
 1      1         1        1
 2      2         1        1
 3      1         2        1
 4      3         2        1

ここで、クエリ結果として次のようにします。

table1.id | table1.name | option | value
-------------------------------------
      1       "one"        1       1
      2       "two"        1       1
      3       "three"    
      1       "one"        2       1
      2       "two"    
      3       "three"      2       1

どうすればそれを達成できますか?

私はすでに試しました:

SELECT
  table1.id,
  table1.name,
  table2.option,
  table2.value
FROM table1 AS table1
LEFT outer JOIN table2 AS table2 ON table1.id = table2.tbl1fk

しかし、結果はnull値を省略しているようです。

1    "one"    1   1
2    "two"    1   1
1    "one"    2   1
3    "three"  2   1

解決済み:MahmoudGamalに感謝:(およびGROUPBY)このクエリで解決済み

SELECT 
  t1.id,
  t1.name,
  t2.option,
  t2.value
FROM
(
  SELECT t1.id, t1.name, t2.option
  FROM table1 AS t1
  CROSS JOIN table2 AS t2
) AS t1
LEFT JOIN table2 AS t2  ON t1.id = t2.tbl1fk
                       AND t1.option = t2.option
group by t1.id, t1.name, t2.option, t2.value
ORDER BY t1.id, t1.name
4

4 に答える 4

8

最初のテーブルからと2番目のテーブルからのCROSS JOIN可能なすべての組み合わせを取得するためにを使用する必要があります。次に、これらの組み合わせを2番目のテーブルと組み合わせます。何かのようなもの:nameoptionLEFT JOIN

SELECT 
  t1.id,
  t1.name,
  t2.option,
  t2.value
FROM
(
  SELECT t1.id, t1.name, t2.option
  FROM table1 AS t1
  CROSS JOIN table2 AS t2
) AS t1
LEFT JOIN table2 AS t2  ON t1.id = t2.tbl1_fk
                       AND t1.option = t2.option

SQLフィドルデモ

于 2013-03-25T12:53:21.977 に答える
3

単純なバージョン:オプション=グループ

Qでは指定されていませんが、なんとかしてグループを定義するオプションのようです。この場合、クエリは次のようになります。

SELECT t1.id, t1.name, t2.option, t2.value
FROM  (SELECT generate_series(1, max(option)) AS option FROM table2) o
CROSS  JOIN table1 t1
LEFT   JOIN table2 t2 ON t2.option = o.option AND t2.tbl1_fk = t1.id
ORDER  BY o.option, t1.id;

1または、オプションに順番に番号が付けられていない場合は、 :で始まります。

...
FROM  (SELECT DISTINCT option FROM table2) o
...

戻り値:

 id | name  | option | value
----+-------+--------+-------
  1 | one   |      1 |     1
  2 | two   |      1 |     1
  3 | three |        |
  1 | one   |      2 |     1
  2 | two   |        |
  3 | three |      2 |     1
  • より速くよりクリーンCROSS JOINで、大きなものと大きなものを避けGROUP BYます。
  • セットごとにグループ番号()を持つ個別の行を取得します。grp
  • Postgres8.4以降が必要です。

より複雑:行のシーケンスによって示されるグループ

WITH t2 AS (
   SELECT *, count(step OR NULL) OVER (ORDER BY id) AS grp
   FROM (
      SELECT *, lag(tbl1_fk, 1, 2147483647) OVER (ORDER BY id) >= tbl1_fk AS step
      FROM table2
      ) x
   )
SELECT g.grp, t1.id, t1.name, t2.option, t2.value
FROM  (SELECT generate_series(1, max(grp)) AS grp FROM t2) g
CROSS  JOIN table1 t1
LEFT   JOIN        t2 ON t2.grp = g.grp AND t2.tbl1_fk = t1.id
ORDER  BY g.grp, t1.id;

結果:

 grp | id | name  | option | value
-----+----+-------+--------+-------
   1 |  1 | one   |      1 |     1
   1 |  2 | two   |      1 |     1
   1 |  3 | three |        |
   2 |  1 | one   |      2 |     1
   2 |  2 | two   |        |
   2 |  3 | three |      2 |     1

->両方のSQLfiddle

どのように?

複雑なバージョンの説明...

  • すべてのセットは、tbl1_fk<=最後のセットで始まります。これはウィンドウ関数lag()でチェックします。最初の行(前の行がない)のコーナーケースをカバーするために、可能な限り最大の整数2147483647をデフォルトとして提供しますlag()

  • 集約ウィンドウ関数として、count()各行に実行カウントを追加し、グループ番号を効果的に形成しgrpます。

  • 次の場合、グループごとに1つのインスタンスを取得できます。

    (SELECT DISTINCT grp FROM t2) g
    

    しかし、最大値を取得generate_series()し、削減されたものに気の利いたものを採用する方が高速CROSS JOINです。

  • これCROSS JOINにより、余剰なしで必要な行が正確に生成されます。後で必要になることを回避しますGROUP BY

  • LEFT JOIN t2grpそれに加えてtbl1_fk、それを区別するために使用します。

  • 好きなように並べ替えることができます。これはグループ番号で可能になりました。

于 2013-03-25T19:38:43.433 に答える
0

これを試して

SELECT
  table1.id, table1.name, table2.option, table2.value  FROM table1 AS table11
JOIN table2 AS table2 ON table1.id = table2.tbl1_fk
于 2013-03-25T12:54:10.183 に答える
-5

これで十分です:

select * from table1 left join table2 on table1.id = table2.tbl1_fk;

于 2013-11-05T09:42:29.117 に答える