Skip to Main Content

Japanese

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Interested in getting your voice heard by members of the Developer Marketing team at Oracle? Check out this post for AppDev or this post for AI focus group information.

MAX関数とNOT EXISTSを用いたサブクエリの解釈のされ方

877759Jul 25 2011 — edited Jul 26 2011
はじめまして。
サブクエリを使用した時の内部的な処理の動きについてご教授ください。
11gを使用しています。

■やりたいこと
T_QUESTION・・・F_SEQUENCE と F_VERSION の複合キー
T_RESULT・・・F_SEQUENCE と F_VERSION の複合キー
というテーブルがあり、
T_QUESTIONの中から、各F_SEQUENCEの最大F_VERSIONの、F_SEQUENCEとF_VERSIONの組み合わせで、
且つその組み合わせがT_RESLUTに存在しないものだけを取得したい。


■テーブル内データ
・T_QUESTION
F_SEQUENCE, F_VERSION
1, 0 ←これと
2, 0 ←これを取得したい
3, 0
3, 1
・T_RESULT
F_SEQUENCE, F_VERSION
3, 1


■意図しない結果を返すSQL:
SELECT
Q.F_QSEQNO,
MAX(Q.F_VERSION)
FROM
T_QUESTION Q
WHERE
NOT EXISTS(SELECT * FROM T_RESULT R WHERE R.F_QSEQNO=Q.F_QSEQNO AND R.F_VERSION=Q.F_VERSION)
GROUP BY F_QSEQNO;
結果は、
F_SEQUENCE:1,F_VERSION:0
F_SEQUENCE:2,F_VERSION:0
F_SEQUENCE:3,F_VERSION:0 ←これは取得したくない。

■自分の解釈
1.一番外側の SELECT Q.F_QSEQNO,MAX(Q.F_VERSION) が実行され、1,0 2,0 3,1 が選択される。
2.選択された 1,0 2,0 3,1 の組み合わせの中からT_RESULTに存在しない組み合わせだけが選択される。

■疑問
1.内側のSELECT * FROM T_RESULT R WHERE R.F_QSEQNO=Q.F_QSEQNO AND R.F_VERSION=Q.F_VERSIONが最初に解釈されるのか?
2.意図した結果を取得するためにはどこを変えたらよいのか?
3.MAX(Q.F_VERSION)にエイリアスを振った場合、そのエイリアスを内側のSELECT文内で使うようなことはできないのか?(使おうとしたら「ORA-00904: "VVV": 無効な識別子です。」というエラーになりました。)

■参考
WHERE句を取り除いた下記SQLを実行すると、
SELECT
Q.F_QSEQNO,
MAX(Q.F_VERSION)
FROM
T_QUESTION Q
GROUP BY F_QSEQNO;
結果は、
F_SEQUENCE:1,F_VERSION:0
F_SEQUENCE:2,F_VERSION:0
F_SEQUENCE:3,F_VERSION:1
となりました。


本格的に勉強し始めたばかりで根本的な間違いがあるかもしれません。
おかしな点や不明瞭な点があればご指摘ください。

以上、宜しくお願い致します。

Comments

Answer

PlSqlCustom3:

( [node^) function_call

| [node^) datetime_literal

| [node^) function_expression

) & ?node = 'TO_DATE'

& ([arg) expr

| [arg) string_literal

| [arg) pls_expr )

& node^ < arg

& [arg+1) ')'

& [arg-1) '('

;

To work out a problem like this it is better to start with expanded parse tree in the structure panel

datetime_literal_parse_tree.png

Witness the parse tree branches of interest highlighted in orange. Apparently, the parser hasn't been consistent, and in all three TO_DATE calls has been recognized differently. This is why we have to use disjunction. Our first query attempt then is:

AllFunctionCalls:

( [node) function_call

| [node) datetime_literal

| [node) function_expression

) ;

Next, we want only TO_DATE calls which, and the function call name is the child of the node that we just have identified. At this point we could have introduced another attribute, but I have chosen to reidentify the node with TO_DATE, and make the parent to be a function call:

AllToDateCalls:

( [node^) function_call

| [node^) datetime_literal

| [node^) function_expression

) & ?node = 'TO_DATE'

;

Next, we have to introduce the second attribute -- arg, and, again, the grammar payload is different in 3 cases. More important, how to connect these two attributes, the node and the arg? It is ancestor-descendant relation, more specifically the closest ancestor-descendant. It is described at page 12 of

https://vadimtropashko.files.wordpress.com/2019/05/arbori-1.pdf

Actually, since we renamed the node to be the function call name only, it is the parent -- node^ -- which is the ancestor of the arg.

The final condition is that a single argument of the TO_DATE function call would have the open and closed parenthesis as sibling parse tree nodes. The result:

datetime_literal_syntax_colors.png

Marked as Answer by Mike Kutz · Sep 27 2020
1 - 1
Locked Post
New comments cannot be posted to this locked post.

Post Details

Locked on Aug 23 2011
Added on Jul 25 2011
3 comments
8,564 views