web-dev-qa-db-fra.com

CROSS/OUTER APPLY dans MySQL

J'ai besoin d'utiliser CROSS APPLY dans MySQL (instance MySQL EC2 RDS). On dirait que MySQL ne reconnaît pas la syntaxe CROSS APPLY. Quelqu'un peut m'aider s'il vous plaît?

Voici la requête.

SELECT ORD.ID
    ,ORD.NAME
    ,ORD.DATE
    ,ORD_HIST.VALUE
FROM ORD
CROSS APPLY (
    SELECT TOP 1 ORD_HISTORY.VALUE
    FROM ORD_HISTORY
    WHERE ORD.ID = ORD_HISTORY.ID
        AND ORD.DATE <= ORD_HISTORY.DATE
    ORDER BY ORD_HISTORY.DATE DESC
    ) ORD_HIST
5
hoz

Votre approximation la plus proche directe est une jointure avec une sous-requête corrélée comme prédicat.

SELECT
   ORD.ID
  ,ORD.NAME
  ,ORD.DATE
  ,ORD_HISTORY.VALUE
FROM
  ORD
INNER JOIN
  ORD_HISTORY
    ON  ORD_HISTORY.<PRIMARY_KEY>
        =
        (SELECT ORD_HISTORY.<PRIMARY_KEY>
           FROM ORD_HISTORY
          WHERE ORD.ID = ORD_HISTORY.ID
            AND ORD.DATE <= ORD_HISTORY.DATE
       ORDER BY ORD_HISTORY.DATE DESC
          LIMIT 1
        )

Dans votre cas, cependant, vous n’avez besoin que d’un seul champ de la table cible. Cela signifie que vous pouvez utiliser la sous-requête corrélée directement dans l'instruction SELECT.

SELECT
   ORD.ID
  ,ORD.NAME
  ,ORD.DATE
  ,(SELECT ORD_HISTORY.VALUE
      FROM ORD_HISTORY
     WHERE ORD.ID = ORD_HISTORY.ID
       AND ORD.DATE <= ORD_HISTORY.DATE
  ORDER BY ORD_HISTORY.DATE DESC
     LIMIT 1
   )   AS VALUE
FROM
  ORD
13
MatBailie

Depuis MySQL 8.0.14, vous pouvez utiliser LATERAL :

Une table dérivée peut maintenant être précédée du mot-clé LATERAL pour indiquer qu'il est autorisé à faire référence aux colonnes des tables précédentes dans la même clause FROM. Une table dérivée spécifiée avec LATERAL ne peut figurer que dans une clause FROM, dans une liste de tables séparées par des virgules ou dans une spécification de jointure (JOIN, INNER JOIN, CROSS JOIN, LEFT [OUTER] JOIN ou RIGHT [OUTER ] JOIN). Les tables dérivées latérales rendent possibles certaines opérations SQL qui ne peuvent pas être effectuées avec des tables dérivées non latérales ou qui nécessitent des solutions de contournement moins efficaces.

CROSS APPLY () <=> ,LATERAL ()
OUTER APPLY () <=> LEFT JOIN LATERAL () ON 1=1

Prise en charge des tables dérivées LATERAL ajoutées à MySQL 8.0.14

Et dans ce cas:

SELECT ORD.ID
    ,ORD.NAME
    ,ORD.DATE
    ,ORD_HIST.VALUE
FROM ORD,
LATERAL (
    SELECT ORD_HISTORY.VALUE
    FROM ORD_HISTORY
    WHERE ORD.ID = ORD_HISTORY.ID
        AND ORD.DATE <= ORD_HISTORY.DATE
    ORDER BY ORD_HISTORY.DATE DESC
    LIMIT 1
    ) ORD_HIST
1
Lukasz Szozda