web-dev-qa-db-ja.com

MySQLでのWITHに相当するMySQL

MySQLにOracleのWITH句に相当するものはありますか?

12
Neeru Sharma

存在しない。開発しない限り(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のコードが重複していることに注意してください。より複雑なクエリでは、コードを複数回記述する必要があります。

16
ypercubeᵀᴹ

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

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

編集:

MySQLでの3つの回避策を明確に公開している同様のスレッドでこの答えを見ました

  • 一時テーブル
  • 派生テーブル
  • インラインビュー(事実上、WITH句が表すもの-それらは交換可能です)

https://stackoverflow.com/a/1382618/290629

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

2
Raúl Moreno