MySQL equivalente a WITH no oracle

12

Existe um equivalente MySQL da cláusula WITH no Oracle?

Neeru Sharma
fonte

Respostas:

16

Não há. A menos que (até) a desenvolva (o MySQL é de código aberto, qualquer pessoa pode contribuir).

A WITHpalavra-chave ANSI / ISO SQL é usada para definir CTEs (Common Table Expressions) e simplifica consultas complexas com uma ou várias referências aninhadas. Está disponível no Oracle, Postgres, SQL-Server, DB2, mas não no MySQL.

A consulta final pode ter referências (geralmente na FROMcláusula, mas podem estar em qualquer outra parte) a qualquer uma das expressões comuns da tabela, uma ou mais vezes. A consulta pode ser escrita (sem CTEs) no MySQL usando tabelas derivadas, mas as referências precisam ser feitas repetidamente.

Exemplo de uma pergunta boba mostrando todas as pessoas nascidas nos anos 50 e no mês de julho e o número de todas as pessoas nascidas no mesmo ano:

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 ;

No MySQL, poderia ser escrito como:

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 ;

Observe a duplicação de código para a tabela derivada a. Em consultas mais complexas, o código teria que ser escrito várias vezes.

ypercubeᵀᴹ
fonte
Para evitar repetições (duplicação de código), não seria melhor usar variáveis ​​e tabelas temporárias?
Pacerier
Eu não me preocuparia com a duplicação de código, mas certamente consideraria e tentaria uma versão com tabelas temporárias, por motivos de desempenho.
precisa saber é o seguinte
1
Por que você diz que não se preocuparia com a duplicação de código? Isso é totalmente bagunçado e  SECO .
Pacerier 30/01
1
O @Pacerier DRY nem sempre é relevante para o código do banco de dados.
JNK
1
@ Pacerier Eu não ficaria surpreso se não fosse. Os mecanismos de banco de dados precisam fazer palpites sobre o que funcionará melhor e, ao mesmo tempo, garantir o retorno de resultados corretos. As tabelas temporárias geralmente são boas, mas o DRY leva a um desempenho terrível nos bancos de dados em outros aspectos, como funções definidas pelo usuário.
JNK
2

Isso funcionará, mas é uma pena que não forneça a vantagem de usar a cláusula WITH, que não é executar a mesma consulta várias vezes (com consultas complexas pode ser realmente lenta e muito exigente para o mecanismo de banco de dados; eu sofri) .

Eu sugeriria inserir cada SELECT definido na cláusula WITH original em sua própria tabela temporária e usá-los dentro da consulta . No MySQL, a tabela temporária se soltará assim que a sessão do usuário terminar.

EDITAR:

Acabei de ver esta resposta em um tópico semelhante que expõe claramente as três soluções alternativas com o MySQL :

  • Tabelas TEMPORÁRIAS
  • Tabelas DERIVADAS
  • visualizações embutidas (efetivamente o que a cláusula WITH representa - elas são intercambiáveis)

/programming//a/1382618/2906290

e um exemplo de procedimento MySQL que cria e elimina as tabelas temporárias , caso você continue com sua sessão e queira liberar esses recursos (eu o usaria apenas como exemplo da sintaxe): /programming//a/ 5553145/2906290

Raúl Moreno
fonte