2013-07-22 3 views
0

Tenir compte de la requête exemple suivant:en utilisant comme valeur plus tard dans la requête

SELECT foo.bar, 
DATEDIFF(
    # Some more advanced logic, such as IF(,,), which shouldn't be copy pasted 
) as bazValue 
FROM foo 
WHERE bazValue >= CURDATE() # <-- This doesn't work 

Comment puis-je faire le bazValue disponible plus tard dans la requête? Je préférerais cela, puisque je crois qu'il suffit de maintenir le code à un endroit si possible.

Répondre

1

Il y a deux façons de contourner ce problème que vous pouvez utiliser dans MySQL:

En utilisant une vue en ligne (ce devrait fonctionner dans la plupart des autres versions de SQL, aussi):

select * from 
(SELECT foo.bar, 
DATEDIFF(
    # Some more advanced logic, such as IF(,,), which shouldn't be copy pasted 
) as bazValue 
FROM foo) buz 
WHERE bazValue >= CURDATE() 

en utilisant une clause HAVING (en utilisant des alias de colonne dans HAVING est spécifique à MySQL):

SELECT foo.bar, 
DATEDIFF(
    # Some more advanced logic, such as IF(,,), which shouldn't be copy pasted 
) as bazValue 
FROM foo 
HAVING bazValue >= CURDATE() 
1

Comme formalisées par Problems with Column Aliases:

standard SQL ne permettant pas des références à des alias de colonne dans une clause WHERE. Cette restriction est imposée car lorsque la clause WHERE est évaluée, la valeur de la colonne n'a peut-être pas encore été déterminée. Par exemple, la requête suivante est illégale:

SELECT id, COUNT(*) AS cnt FROM tbl_name 
WHERE cnt > 0 GROUP BY id; 

La clause WHERE détermine les lignes devraient être incluses dans la clause GROUP BY, mais il fait référence à l'alias d'une valeur de colonne qui est pas connue jusqu'à ce que les lignes ont été sélectionné et groupé par GROUP BY.

Vous pouvez toutefois réutiliser l'expression aliasées et si elle utilise des fonctions déterministes l'Optimiseur de requête fera en sorte que les résultats mises en cache sont réutilisés:

SELECT foo.bar, 
     DATEDIFF(
     -- your arguments 
     ) as bazValue 
FROM foo 
WHERE DATEDIFF(
     -- your arguments 
     ) >= CURDATE() 

Vous pouvez déplacer le filtre dans une clause HAVING (où les colonnes aliasées auront déjà été calculées et sont donc disponibles) - mais les performances en souffriront car les index ne peuvent pas être utilisés et le filtre ne sera pas appliqué avant la compilation des résultats.

+0

Merci pour le devis! Je suis conscient que je peux copier-coller toute la logique, mais j'essaie d'éviter ça .. – Zar

1

Comme MySQL ne supporte pas les CTE, pensez à utiliser inline view:

SELECT foo.bar, 
FROM foo, 
(SELECT DATEDIFF(
    # Some more advanced logic, such as IF(,,), which shouldn't be copy pasted 
    ) as bazValue 
) AS iv 
WHERE iv.bazValue >= CURDATE() 
Questions connexes