OracleのWITHと同等のMySQL


回答:


16

存在しない。開発するまで(MySQLはオープンソースである限り、誰でも貢献できます。)

ANSI / ISO SQL WITHキーワードは、共通テーブル式(CTE)を定義するために使用され、1つまたは複数のネストされた参照を持つ複雑なクエリを簡素化します。Oracle、Postgres、SQL-Server、DB2で使用できますが、MySQLでは使用できません。

最終的なクエリにはFROM、一般的なテーブル式のいずれかへの参照(通常は句の中にありますが、他の部分にある場合があります)が1回以上あります。クエリは、派生テーブルを使用してMySQLで(CTEなしで)記述できますが、参照を繰り返し行う必要があります。

50代と7月に生まれたすべての人と同じ年に生まれたすべての人の数を示す愚かなクエリの例:

WITH a AS
    ( SELECT name, birthdate, YEAR(birthdate) AS birthyear
      FROM persons
      WHERE birthdate >= '1950-01-01' AND birthdate < '1960-01-01' 
    ) 
, b AS
    ( SELECT birthyear, COUNT(*) AS cnt
      FROM a
      GROUP BY birthyear 
    ) 
SELECT a.name, a.birthdate, b.cnt AS number_of_births
FROM a JOIN b
  ON a.birthyear = b.birthyear 
WHERE MONTH(a.birthdate) = 7 ;

MySQLでは、次のように記述できます。

SELECT a.name, a.birthdate, b.cnt AS number_of_births
FROM 
    ( SELECT name, birthdate, YEAR(birthdate) AS birthyear
      FROM persons
      WHERE birthdate >= '1950-01-01' AND birthdate < '1960-01-01' 
    ) AS a 
  JOIN 
    ( SELECT birthyear, COUNT(*) AS cnt
      FROM 
        ( SELECT name, birthdate, YEAR(birthdate) AS birthyear
          FROM persons
          WHERE birthdate >= '1950-01-01' AND birthdate < '1960-01-01' 
        ) AS aa
      GROUP BY birthyear
    ) AS b
  ON a.birthyear = b.birthyear 
WHERE MONTH(a.birthdate) = 7 ;

派生テーブルのコードの重複に注意してくださいa。より複雑なクエリでは、コードを複数回記述する必要があります。


繰り返し(コードの重複)を避けるには、変数と一時テーブルを使用した方が良いと思いませんか?
パセリエ

コードの重複については心配しませんが、パフォーマンス上の理由から、一時テーブルを含むバージョンを検討して試してみます。
ypercubeᵀᴹ

1
コードの重複を心配しないと言うのはなぜですか?これは完全に厄介と国連で  DRY
Pacerier

1
@Pacerier DRYは常にDBコードに関連するとは限りません。
JNK

1
@Pacerierそうでなければ驚かないでしょう。DBエンジンは、正しい結果を返すことを保証しながら、何が最適に機能するかについて知識に基づいた推測を行う必要があります。一般に一時テーブルは問題ありませんが、DRYは、ユーザー定義関数のような他の点でDBのひどいパフォーマンスにつながります。
JNK

2

それはうまくいきますが、WITH句を使用する利点が提供されないのは残念です。つまり、同じクエリを数回実行することはありません(複雑なクエリでは、非常に遅くなり、データベースエンジンに非常に負荷がかかる可能性があります;私はそれに苦しみました) 。

元のWITH句で定義された各SELECTを独自の一時テーブルに挿入し、クエリ内で使用することをお勧めします。MySQLでは、ユーザーセッションが終了すると、一時テーブルは自動的に削除されます。

編集:

MySQLの3つの回避策を明らかにする同様のスレッドでこの答えを見ました:

  • 一時テーブル
  • 派生テーブル
  • インラインビュー(実質的にWITH句が表すもの-交換可能)

/programming//a/1382618/2906290

セッションを続行し、それらのリソースを解放したい場合に一時テーブルを作成および削除するMySQLプロシージャの例(構文の例として使用します):https : //stackoverflow.com/a/ 5553145/2906290

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.