OLAP 番号付け関数 の ROW_NUMBER OVER()
のOVER()
内に明示的な ORDER BY
を記述していないと、番号付けに曖昧さが残り ハマル よってお話です。
今回のケースとしては、IBMi V7R2 → V7R5 にした時でしたが、他のバージョンの組合でも当然あり得るでしょう。
(※因みに名誉のために言わせて頂くと、今回は調査依頼を受けたケースで私の話では無いです)
そもそも間違っている曖昧さのあるSQLが以下の様にあります。
OVER()
の中にORDER BY
が無く曖昧さは残っていますね。
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
の内容の物理順は以下です。
-CUSNUM-
938472
839283
392859
938485
397267
389572
846283
475938
693829
593029
192837
583990
V7R2 の場合SQLに対する結果が以下のように返り、外側のORDER BY
がサブクエリ内のOVER
に反映された状態となり、あたかもOVER(ORDER BY)が出来ていると錯覚しますね。
-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などが適用されるタイミングで、いつ挙動が変わるか分かりませんね。
-RRN- -CUSNUM-
4 938485
1 938472
2 839283
5 397267
3 392859
この結果から、V7R5未満 で V7R5以降 へリプレースした際 OVER()
にORDER BY
が未指定のアプリケーションが存在すると、挙動の変更を発生し思わぬリスクを発生する事が分かります。
みなさん、OVER(ORDER BY)
忘れないように。
アプリがフレームワーク使っていると吸収してくれるので意識しませんがね。(^o^)