PostgreSQLには、1対多の関係を持つ2つのテーブルがあります。 「1つ」ごとに「多く」のテーブルから1つの結果しか得られないように、それらを結合する必要があります。それだけでなく、「多くの」テーブルから特定の結果を特定する必要があります。
TABLE_A ID |名前|日付|その他のCOLS .... 1 |ジョン| 2012-01-10 | .... 2 |リザ| 2012-01-10 | .... 3 |アニー| 2012-01-10 | .... 4 |ジェームス| 2012-01-10 | .... ... TABLE_B ID | CODE1 | CODE2 | SORT 1 | 04020 | 85003 | 1 1 | 04030 | 85002 | 4 2 | 81000 | 80703 | 1 3 | 87010 | 80102 | 4 3 | 87010 | 84701 | 5 4 | 04810 | 85003 | 1 4 | 04030 | 85002 | 4 4 | 04020 | 85003 | 1 ... QUERY RESULT ID |名前|日付| CODE1 | CODE2 1 |ジョン| 2012-01-10 | 04020 | 85003 2 |リザ| 2012-01-10 | 81000 | 80703 3 |アニー| 2012-01-10 | 87010 | 80102 4 |ジェームス| 2012-01-10 | 04810 | 85003 ...
TABLE_BのSORT列は、実際にはCODE2の最後の文字です。 CODE2は1-9で終わることができますが、3が最も重要で、5、7、4、2、1、0、6、8、9、したがって3-> 1、5-> 2、7-> 3などです。前方へ。
私が直面している問題は、sortが最小の数値であるTABLE_Bの行が必要なことです。場合によっては、複数の最小ケースがあり(TABLE_BのID = 4を参照)、最小IDの行のどれを選択してもかまいませんが、そのIDの結果は1つだけです。
PostgreSQLのDISTINCT ON
を使用すると、よりシンプルに、より短く、より速くなります。
SELECT DISTINCT ON (a.id)
a.id, a.name, a.date, b.code1, b.code2
FROM table_a a
LEFT JOIN table_b b USING (id)
ORDER BY a.id, b.sort
詳細、説明、ベンチマーク、および この密接に関連する回答 のリンク。
私はLEFT JOIN
を使用しているので、table_a
に一致する行がないtable_b
の行は削除されません。
サイドノート:
PostgreSQLでは許可されていますが、列名としてdate
を使用することは賢明ではありません。これは、すべてのSQL標準では 予約語 であり、PsotgreSQLでは型名です。
ID列にid
という名前を付けることもアンチパターンです。説明的ではなく、役に立たない。 (多くの)可能な命名規則の1つは、主キーであるテーブルにちなんで名前を付けることです:table_a_id
。それを参照する外部キーの同じ名前(他の自然名が優先されない場合)。
PostgreSQLはウィンドウ関数をサポートします。これを試して、
SELECT d.ID, d.NAME, d.DATE, d.CODE1, d.CODE2
FROM
(
SELECT a.ID, a.NAME, a.DATE,
b.CODE1, b.CODE2,
ROW_NUMBER() OVER(PARTITION BY a.ID ORDER BY b.SORT ASC, b.CODE2 DESC) AS ROWNUM
FROM TableA a
INNER JOIN TableB b
ON a.ID = b.ID
) d
WHERE d.RowNum = 1
これが私がSQLServerで行うことです。
SELECT a.ID,
a.NAME,
a.DATE,
b.CODE1,
b.CODE2
FROM TABLE_A a
JOIN TABLE_B b
on a.ID = b.ID
WHERE b.SORT = (SELECT MIN(SORT)
FROM TABLE_B
WHERE ID = b.ID)