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
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
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