PRODUCTとMANUFACTURERの2つのテーブルがあります
表1:PRODUCT、列:PRODUCT_ID、PRODUCT_NAME
表2:MANUFACTURER、列:PRODUCT_ID、MANF_ID、ITEM_NO、DEFAULT_MANF
MANUFACTURERテーブルから製品のデフォルトの製造を選択する必要があります。デフォルトのメーカーが利用できない場合、MANUFACTURERテーブルからITEM_NOでメーカーを選択します。
私はこれについてのクエリを以下のように書いています:
SELECT p.PRODUCT_ID, p.PRODUCT_NAME, m.MANF_ID, m.ITEM_NO, m.DEFAULT_MANF
FROM PRODUCT p
INNER JOIN MANUFACTURER m on p.PRODUCT_ID = m.PRODUCT_ID
WHERE p.PRODUCT_ID = 'PROD001'
AND m.MANF_ID = (SELECT TOP 1 MANF_ID FROM MANUFACTURER man WHERE man.PRODUCT_ID = p.PRODUCT_ID and coalesce(man.DEFAULT_MANF, 'N') = 'Y' ORDER BY man.DEFAULT_MANF, man.MANF_ID )
このクエリはSQL Serverでは期待どおりに機能しますが、Oracleではクエリで「TOP」を使用しているため機能しません。
SQL ServerとOracleの両方で機能するようにクエリを変更する方法はありますか?
Oracleのバージョンが12以上の場合、FETCH FIRST n ROWS ONLY
(doc link) を使用できます。
SELECT p.PRODUCT_ID, p.PRODUCT_NAME, m.MANF_ID, m.ITEM_NO, m.DEFAULT_MANF
FROM PRODUCT p
INNER JOIN MANUFACTURER m on p.PRODUCT_ID = m.PRODUCT_ID
WHERE p.PRODUCT_ID = 'PROD001'
AND m.MANF_ID = (SELECT MANF_ID FROM MANUFACTURER man WHERE man.PRODUCT_ID = p.PRODUCT_ID and coalesce(man.DEFAULT_MANF, 'N') = 'Y' ORDER BY man.DEFAULT_MANF, man.MANF_ID FETCH FIRST 1 ROWS ONLY)
Oracle 11以前を使用している場合は、代わりにrownum=1
を使用する必要があります。
スキーマが適切に設計されていれば、製品のデフォルトのメーカーは1つしかなく、サブクエリは必要ないことを付け加えます。
ただし、実際に質問に答えるために、row_number
を悪用することができます。
SELECT p.PRODUCT_ID, p.PRODUCT_NAME, m.MANF_ID, m.ITEM_NO, m.DEFAULT_MANF
FROM PRODUCT p
INNER JOIN MANUFACTURER m on p.PRODUCT_ID = m.PRODUCT_ID
WHERE p.PRODUCT_ID = 'PROD001'
AND m.MANF_ID = (
SELECT MANF_ID FROM (
SELECT MANF_ID, ROW_NUMBER() OVER (ORDER BY man.DEFAULT_MANF, man.MANF_ID) as RN
FROM MANUFACTURER man
WHERE man.PRODUCT_ID = p.PRODUCT_ID
and coalesce(man.DEFAULT_MANF, 'N') = 'Y'
) HACK
WHERE RN=1
);