6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ROW_NUMBER OVER()にちゃんと明示的にORDER BY は書きましょう

Last updated at Posted at 2024-08-01

OLAP 番号付け関数 の ROW_NUMBER OVER()OVER() 内に明示的な ORDER BY を記述していないと、番号付けに曖昧さが残り ハマル よってお話です。
今回のケースとしては、IBMi V7R2V7R5 にした時でしたが、他のバージョンの組合でも当然あり得るでしょう。
(※因みに名誉のために言わせて頂くと、今回は調査依頼を受けたケースで私の話では無いです)

そもそも間違っている曖昧さのあるSQLが以下の様にあります。
OVER()の中にORDER BYが無く曖昧さは残っていますね。

sql.間違った再現SQL.sql
SELECT * FROM(
SELECT
ROW̲NUMBER() OVER() AS RRN
,T1.CUSNUM
FROM QIWS.QCUSTCDT AS T1
)
WHERE RRN BETWEEN 1 AND 5
ORDER BY CUSNUM DESC

SQLが参照するテーブル QIWS.QCUSTCDT の内容の物理順は以下です。

PF.QIWS/QCUSTCDT
-CUSNUM-
938472
839283
392859
938485
397267
389572
846283
475938
693829
593029
192837
583990

V7R2 の場合SQLに対する結果が以下のように返り、外側のORDER BY がサブクエリ内のOVERに反映された状態となり、あたかもOVER(ORDER BY)が出来ていると錯覚しますね。

sql.①V7R2の結果
-RRN- -CUSNUM-
1      938485
2      938472
3      846283
4      839283
5      693829

V7R5 の場合SQLに対する結果が以下のように返ります。
こちらは物理順を踏襲しているためORDER BYが無指定ならば物理順で返えるならば、それはそうかとある意味納得できます。ただ物理順である曖昧さを回避するのであればやはり ORDER BY RRN(T1) が必要でしょう。
因みに V7R5 のACSやPython、PHP、SQLRPGLEは ②V7R5の結果 を返しますが、STRSQLは ①V7R2の結果”今のところ” 返します。
PTFなどが適用されるタイミングで、いつ挙動が変わるか分かりませんね。

sql.②V7R5の結果
-RRN- -CUSNUM-
4      938485
1      938472
2      839283
5      397267
3      392859

この結果から、V7R5未満V7R5以降 へリプレースした際 OVER()ORDER BYが未指定のアプリケーションが存在すると、挙動の変更を発生し思わぬリスクを発生する事が分かります。
みなさん、OVER(ORDER BY) 忘れないように。
アプリがフレームワーク使っていると吸収してくれるので意識しませんがね。(^o^)

6
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?