ストアドプロシージャをSQL ServerからOracleに変換して、互換性があるようにするのに苦労しています。
タイムスタンプに基づいて、いくつかのテーブルの最新のレコードを返すクエリがあります。
SQL Server:
SELECT TOP 1 *
FROM RACEWAY_INPUT_LABO
ORDER BY t_stamp DESC
=>それは私に最新の記録を返します
しかしOracle:
SELECT *
FROM raceway_input_labo
WHERE rownum <= 1
ORDER BY t_stamp DESC
=> ORDER BY
ステートメントに関係なく、これは私に最も古いレコードを(おそらくインデックスに依存して)返します。
私の要件に合わせて、このようにOracleクエリをカプセル化しました。
SELECT *
FROM
(SELECT *
FROM raceway_input_labo
ORDER BY t_stamp DESC)
WHERE rownum <= 1
そしてそれはうまくいきます。しかし、それは私にとって恐ろしいハックのように思えます。特に、関連するテーブルにたくさんのレコードがある場合はそうです。
これを達成するための最良の方法は何ですか?
where
ステートメントが実行されます前order by
。だから、あなたの希望するクエリは "最初の行を取り、それからそれを順序付けるt_stamp
desc"と言っています。そしてそれはあなたが意図するものではありません。
サブクエリメソッドは、Oracleでこれを実行するための適切な方法です。
両方のサーバーで機能するバージョンが必要な場合は、次のものを使用できます。
select ril.*
from (select ril.*, row_number() over (order by t_stamp desc) as seqnum
from raceway_input_labo ril
) ril
where seqnum = 1
外側の*
は最後の列に "1"を返します。これを避けるには、列を個別にリストする必要があります。
代わりにROW_NUMBER()
を使用してください。 ROWNUM
は疑似列、ROW_NUMBER()
は関数です。あなたはそれらの違いについて読み、以下のクエリの出力の違いを見ることができます。
SELECT * FROM (SELECT rownum, deptno, ename
FROM scott.emp
ORDER BY deptno
)
WHERE rownum <= 3
/
ROWNUM DEPTNO ENAME
---------------------------
7 10 CLARK
14 10 MILLER
9 10 KING
SELECT * FROM
(
SELECT deptno, ename
, ROW_NUMBER() OVER (ORDER BY deptno) rno
FROM scott.emp
ORDER BY deptno
)
WHERE rno <= 3
/
DEPTNO ENAME RNO
-------------------------
10 CLARK 1
10 MILLER 2
10 KING 3
このユースケースで私が提案する代替案は、最新の行を取得するためにMAX(t_stamp)を使用することです。
select t.* from raceway_input_labo t
where t.t_stamp = (select max(t_stamp) from raceway_input_labo)
limit 1
私のコーディングパターンの好みは(おそらく)信頼でき、一般的にソートされたリストから最初の行を選択しようとするかそれ以上のパフォーマンスを発揮します - また意図はより明示的に読めます。
お役に立てれば ...
SQLer
上記のコメントで、これに関する設計上の問題点を文書化しました。短い話ですが、Oracleでは、大きなテーブルや同じカラム名を持つテーブルがある場合は、結果を手動で制限する必要があります(それらすべてを明示的に入力して名前を変更したくない場合)。簡単な解決策は、ブレークポイントを見つけ出し、それをクエリで制限することです。競合する列名の制約がない場合は、内部クエリでこれを行うこともできます。例えば。
WHERE m_api_log.created_date BETWEEN TO_DATE('10/23/2015 05:00', 'MM/DD/YYYY HH24:MI')
AND TO_DATE('10/30/2015 23:59', 'MM/DD/YYYY HH24:MI')
結果を大幅に削減します。それから、ORDER BYまたは外側のクエリを実行して行を制限することもできます。
また、TOADには行を制限する機能があると思います。しかし、それがOracleの実際のクエリ内で制限されているかどうかはわかりません。わからない。