Skip to Content
Author's profile photo Sawa Ito

SAP SQL Anywhere における CROSS APPLY と OUTER APPLY (過去のブログ記事より)

このページは、以下の英語ページの抄訳です。最新の情報については、英語ページを参照してください。

 

この記事のオリジナルは、Glenn Paulley が sybase.com に2008年7月に掲載したものです。Glenn はこの記事でSQL Anywhere におけるSQL のサポートについて解説しています。

ここでは、アナリストのトップ10リストには載らないような SQL 言語の機能について注目したいと思います。その SQL の機能とは、APPLY です。APPLY は、FROM 句の SQL 文で以下のような形で使用します。

table-expression  [CROSS | OUTER] APPLY  table-expression

APPLY 演算子は、join 演算子の位置に使用します。join と同様、APPLY は 2つのテーブル式で機能します。左テーブル式と右テーブル式です。しかしながら、APPLY 演算子は、ON 句は使用しません — ON 条件は、非明示的に 1=1 です。そのかわり、明示的な join の条件では、右テーブル式は、左テーブル式への 外部参照を含む可能性があります(そして通常そうです)。右テーブル式は、左テーブル式からのそれぞれの行ごとに評価されます。そして、最終結果は、全ての行の結果の組み合わせになります。

例えば:

以下のプロシージャーについて考えてみてください。これは、ある任意の部門において給料が$80,000よりも大きい従業員の名前を全て返します。

CREATE PROCEDURE high_salary( IN dept INTEGER )
RESULT ( name LONG VARCHAR )
BEGIN
    SELECT E.emp_fname || ' ' || E.emp_lname
        FROM Employee E
        WHERE E.dept_id = dept AND E.salary > 80000;
END

以下のクエリでは、CROSS APPLY を使ってその部門テーブルの各行を high_salary プロシージャーの結果に join します。このプロシージャーは、部門テーブルの各行ごとに評価されます。

SELECT D.dept_name, HS.name
FROM Department D CROSS APPLY high_salary( D.dept_id ) as HS

CROSS APPLY のセマンティックスは、Cartesian プロシージャーまたは、内部 join と似ています。left-outer join セマンティクスには、OUTER APPLY を利用することができます。例として、以下の文では、OUTER APPLY を使って部門テーブルの各ローを high_salary プロシージャーの結果に join します。これにより、部門テーブルの行を保持し、high_salary プロシージャーは何の行も返しません。

SELECT D.dept_name, HS.name
FROM Department D OUTER APPLY high_salary( D.dept_id ) as HS

するどい読者の皆さんは、APPLY と、他のテーブル式のタイプの構造とは違いがほとんどないことに気づいたかもしれません。本質的には、CROSS APPLY は join 条件 1=1 で CROSS JOIN と同一です。同様に、OUTER APPLY は、意味的には 外部 JOINと同等です。例として、以下のクエリは、前の例と同等ですが、OUTER APPLY の右側として導き出されたテーブルを使用します。

SELECT D.dept_name, HS.name
FROM Department D OUTER APPLY (
        SELECT E.emp_fname || ' ' || E.emp_lname
        FROM Employee E
        WHERE E.dept_id = D.dept_id AND E.salary > 80000
    ) HS( name )

LATERAL との比較

APPLY 演算子と同様、LATERAL キーワードも同じ FROM 句内のテーブル間の参照の使用を可能にするために使用します。LATERAL と同様、APPLY は、テーブル関数(ストアドプロシージャー)を含め、導き出されたテーブルでもテーブル式のどちらでも使用できます。しかしながら、APPLY 演算子と LATERAL キーワードの間には、2つの微妙な違いがあります。

LATERAL キーワードは、NULL-supply rows はできませんが、OUTER APPLY は可能です。また、LATERAL で導き出されたテーブルは、その導き出されたテーブルと外部参照はカンマで分ける必要があります。APPLY 演算子では、右のテーブル式と外部参照はカンマでは分けられませんが、その他のどの join 演算子でも分けることができます。言い換えれば、APPLY 演算子は、左テーブル式内のどのテーブルへの参照も可能ですが、LATERAL キーワードでは、現在のテーブル式の外側のテーブルへの参照が可能です。

APPLY 演算子は、LHS のテーブル式は可能な限り全ての join を含むのに対し、RHS のテーブル式は単一のテーブルノードのみ含むよう解析されるということに注意する必要があります。

A JOIN B OUTER APPLY C JOIN D is parsed as ((A JOIN B) OUTER APPLY C) JOIN D.

これは、かっこなしのネストされた (outer) join テーブル式と同じルールに従っています。結果として、APPLY の RHS 上のテーブルは、join によるAPPLY 演算子とは別に、LHS のテーブルを参照することが可能です。しかし、右の join によって APPLY から分けられたテーブルは、左のテーブルを参照することはできません。

例えば:

  • SELECT * FROM A CROSS JOIN B OUTER APPLY some_procedure(A.x) CROSS JOIN D  // エラーはありません。
  • SELECT * FROM A CROSS JOIN B OUTER APPLY C CROSS JOIN some_procedure(B.x)  // エラーです。B.x は、CROSS JOIN の LHS の最即時テーブル式からではありません。

また、LATERAL キーワードとは異なり、SQL Anywhere は APPLY で導き出したテーブルの特別なクエリ式シンタックスはサポートしていません。

  • SELECT * FROM A, ( B JOIN C ON B.x=C.x ) dt  // シンタックスエラーです。後のテーブル式に LATERAL なしに相関名を与えることができません。
  • SELECT * FROM A, LATERAL( B JOIN C ON B.x=A.x ) dt   // エラーはありません。A.x への参照は dt の使用のように LATERAL によって可能です。
  • SELECT * FROM A OUTER APPLY ( B JOIN C ON B.x=A.x ) dt // シンタックスエラーです。OUTER APPLY で導き出されたテーブル名 dt を指定することができません。

CROSS APPY と OUTER APPLY は、ANSI SQL 標準のものではありません。これらは、Microsoft SQL Server との互換性のためにサポートしているものです。

===

 

SAP SQL Anywhere に関する詳細情報は、SAP SQL Anywhere Communityページ<英語> を参照してください。

 

上記のコミュニティーに掲載されている技術情報は、順次SQL Anywhere 日本語コミュニティ

に掲載しています。

 

SQL Anywhere に関してはまずはこちらをご参照ください。無期限でご利用いただける無償の Developers Edition もこちらからダウンロードが可能です。

 

SQL Anywhere に関して技術的な質問のある方はコミュニティに登録し、
「Ask a Question」機能をご利用ください。

Language には「Japanese」、
Primary Tag には「SAP SQL Anywhere」を選択
User Tagに「sql anywhere」「sql anywhere Japanese question」

を入力してください。

不具合につきましては、サポート契約者様専用の問い合わせ方法にてお問い合わせください。

 

======================
ご購入に関するお問い合わせ

こちらよりお問い合わせください。

Assigned Tags

      Be the first to leave a comment
      You must be Logged on to comment or reply to a post.