2009-04-22 6 views
1

Comment puis-je réutiliser une colonne calculée dans SQL dans MySQL? Dis: ma requête est quelque chose comme: -Réutilisation de colonnes calculées dans mysql

SELECT 
    CONVERT_TZ(
     if(timestamp_start > last_update, timestamp_start, last_update), 
     'GMT', 
     user.timezone 
    ) as time_usr_tz 
from 
    shecdule 
    inner join user on shecdule.user_id = user.user_id 
where 
    CONVERT_TZ(
     if(timestamp_start > last_update, timestamp_start, last_update), 
     'GMT', 
     user.timezone 
    ) 
    < CURRENT_TIMESTAMP(); 

Si vous voyez la requête est répétée la partie « CONVERT_TZ ..... ».

Ceci est seulement un exemple d'interrogation. En fait, je dois utiliser cette colonne calculée plusieurs fois. Donc, si je change en un endroit, je dois changer à plusieurs endroits. Et la taille de la requête devient effrayante, aussi.

Est-il possible d'éviter une telle duplication?

MISE À JOUR J'ai déjà sous-requête dans ma requête d'origine, donc sous-requête n'est pas une option préférable. Est-ce possible d'une autre manière?

Répondre

4
SELECT ctz 
FROM (
     SELECT shecdule.*, 
       CONVERT_TZ(
       if(timestamp_start > last_update, timestamp_start, last_update), 
       'GMT', 
       user.timezone 
       ) AS ctz 
     FROM shecdule 
     INNER JOIN 
       user 
     ON  user.user_id = s.user_id 
     ) s 
WHERE ctz < CURRENT_TIMESTAMP() 

Notez que cette requête ne pas utiliser les index sur timestamp_start et last_update efficacement.

Voir les détails de performance dans l'article dans mon blog:

En deux mots, il vaut mieux utiliser ceci:

SELECT ctz 
FROM (
     SELECT shecdule.*, 
       CONVERT_TZ(
       if(timestamp_start > last_update, timestamp_start, last_update), 
       'GMT', 
       user.timezone 
       ) AS ctz 
     FROM shecdule 
     INNER JOIN 
       user 
     ON  user.user_id = s.user_id 
     WHERE timestamp_start < CURRENT_TIMESTAMP() + INTERVAL 14 HOUR 
       OR last_update < CURRENT_TIMESTAMP() + INTERVAL 14 HOUR 
     ) s 
WHERE ctz < CURRENT_TIMESTAMP() 

Cette requête intérieure interprétera grossière en filtrant sur timestamp_start et last_update en utilisant des index (aucune conversion de zone ne peut compenser le temps de plus de +14:00 heures de).

La sous-requête externe filtre ensuite finement les résultats en fonction du fuseau horaire de l'utilisateur.

Si vous ne l'aimez pas les sous-requêtes, vous pouvez également utiliser:

SELECT shecdule.*, 
     CONVERT_TZ(
     if(timestamp_start > last_update, timestamp_start, last_update), 
     'GMT', 
     user.timezone 
     ) AS ctz 
FROM shecdule 
INNER JOIN 
     user 
ON  user.user_id = s.user_id 
/* 
     WHERE timestamp_start < CURRENT_TIMESTAMP() + INTERVAL 14 HOUR 
       OR last_update < CURRENT_TIMESTAMP() + INTERVAL 14 HOUR 
*/ 
HAVING ctz < CURRENT_TIMESTAMP() 
Questions connexes