2011-01-20 5 views
0

J'ai une table avec des donnéesrequête mySQL - sélectionnez conditionnelle

t1 
------------------ 
id (int) 
item_id (int) 
item_description (text) 
showHide (enum 0,1) 

Normalement, je montre des résultats qui ont drapeau showhide réglé sur « 0 ». J'ai besoin de modifier la requête pour montrer aussi les résultats avec l'indicateur showHide mis à '1' si l'utilisateur a l'item_id correspondant dans une autre table, t2.

t2 
------------------ 
id (int) 
item_id (int) 
usr_id (int) 

Coincé ici, pas sûr comment faire:

SELECT item_description FROM t1 
// get results with showHide = 0 
// AND 
// showHide = 1 if t1.item_id found in t2 WHERE usr_id = 123 

Répondre

1

Il suffit de combiner 2 requêtes avec UNION

SELECT t1.item_description 
    FROM t1 
WHERE showHide = 0 
UNION 
    SELECT t1.item_description 
     FROM t1 
INNER JOIN t2 ON t1.item_id = t2.item_id 
    WHERE showHide = 1 

La façon plus délicate, donc moins performant:

SELECT t1.item_description 
     FROM t1 
LEFT JOIN t2 ON t1.item_id = t2.item_id 
    WHERE showHide = 0 
     OR (showHide = 1 AND t2.item_id IS NOT NULL) 
+1

Je ne vois pas comment «plus rusé» implique «moins performant». Je ne prétends pas que la deuxième solution pourrait être en fait pire (pas jusqu'à l'analyse comparative), mais ne vois pas la relation entre «trickiness» (un terme subjectif pour le moins) et performance. – Mchl

+0

@Mchl: c'est ** moins ** performant parce que: 1) 'LEFT JOIN' (qui est plus lent que' INNER JOIN' 2) 'OR' avec champ 0/1 (puisque mysql ** n'a pas ** index de type bitmap) ne sera pas optimisé du tout (il sera fullscan dans tous les cas). – zerkms

+0

@Mchl: la connexion entre 'trick' et' performance' dans mon esprit est la suivante: la requête la plus simple et la plus évidente fonctionne presque toujours mieux. Prouvé pour des années. – zerkms

1
SELECT 
    t1.item_description 
FROM 
    t1 
LEFT JOIN (
    SELECT item_id FROM t2 WHERE usr_id = 123 
) AS t2 
USING (item_id) 
WHERE 
    t1.showHide = 0 
OR 
    (t1.showHide = 1 AND t2.item_id IS NOT NULL) 
+0

La sélection imbriquée au lieu de 'join' avec' ON' peut diminuer considérablement les performances. – zerkms

+0

C'est une sous-requête non corrélée. Sauf si vous travaillez sur MySQL 4.x cela fonctionne très bien. – Mchl

+1

@Mchl: le fait qu'il ne soit pas corrélé ne signifie pas que mysql l'exécutera une seule fois. Pour mysql c'est vrai, que quelque chose écrit dans la documentation n'est pas absolument vrai irl. Aussi - vous perdez la possibilité d'utiliser l'index composite ('user_id + item_id') pour accélérer votre requête, et pour rechercher' USING (item_id) 'vous ** obtenez ** toujours un scan sur l'ensemble de résultats de la requête imbriquée . – zerkms