2009-10-20 8 views
4

J'ai un SQL qui peut être simplifié à:Comment éliminer les calculs en double dans SQL?

SELECT * 
    FROM table 
WHERE LOCATE(column, :keyword) > 0 
ORDER BY LOCATE(column, :keyword) 

Vous pouvez voir qu'il ya un double de « Locate (colonne: mot-clé) ». Y a-t-il un moyen de le calculer une seule fois?

+1

En outre, dans le cas où vous ne saviez pas De nombreuses bases de données vous permettent de créer un index sur une fonction ou un calcul. Donc, si vous vous trouvez à faire beaucoup de requêtes basées sur LOCATE (column,: keyword), vous pouvez créer un index où cette valeur a été précalculée et stockée, pour augmenter la vitesse des requêtes. –

+1

Êtes-vous sûr que LOCATE est appelé deux fois? – tster

+0

tster est correct - de nombreux moteurs sql optimisent cela. –

Répondre

2

AYANT travaille avec des alias dans MySQL:

SELECT *, LOCATE(column, :keyword) AS somelabel 
FROM table 
HAVING somelabel > 0 
ORDER BY somelabel 
+0

Notez que HAVING calcule l'ensemble des résultats, puis le filtre. OERE filtre ligne par ligne, en économisant de la mémoire. –

+0

Non seulement la mémoire, si la condition peut être évaluée à partir d'un index chargé, il peut également enregistrer des E/S. – Unreason

5
SELECT *, LOCATE(column, :keyword) AS somelabel 
FROM table 
WHERE somelabel > 0 
ORDER BY somelabel 
+0

Mais je suis une erreur sur MySQL # 1054 - Unknown column 'c1' dans 'where' Le SQL est: SELECT * , locate (nom, 'a') AS c1 FROM 'employees' c1> 0 – Cheng

+0

Cette méthode ne fonctionnera pas pour toutes les bases de données. Certains vous demanderont toujours de référencer explicitement la fonction dans la clause de commande. –

+0

Est-ce que cela fonctionne même pour MySQL? http://dev.mysql.com/doc/refman/5.4/en/select.html "Il n'est pas autorisé de faire référence à un alias de colonne dans une clause WHERE, car la valeur de la colonne n'est peut-être pas encore déterminée lorsque la clause WHERE est exécuté " – MartW

2

Jeff Ober a la bonne idée, mais voici une méthode alternative:

SELECT 
    t.* 
,loc.LOCATED 
FROM 
    table t 
    INNER JOIN 
    (
    SELECT 
    primary_key 
    ,LOCATE(column,:keyword) AS LOCATED 
    FROM 
    table 
) loc 
    ON t.primary_key = loc.primary_key 
WHERE loc.LOCATED > 0 
ORDER BY 
    loc.LOCATED 
Questions connexes