2009-09-03 7 views
0

Im réviser mon script de recherche de style auto-complète. Le site dispose de 2 catégories ... films et émissions de télévision. À l'heure actuelle, la chaîne de requête complète-auto ressemble à ceci:Comment récupérer deux types de données avec une seule requête mysql?

SELECT * FROM movies WHERE mov_title LIKE '%" . $queryString . "%' AND mov_status = 1 AND mov_incomplete = 0 ORDER BY mov_type, mov_title LIMIT 10 

Le problème est s'il y a plus de 10 matchs avec mov_type = 1 (puisqu'il ordonne par type premier), il n'y aura aucune mov_type = 2 enregistrements, cela ferait partie des résultats.

Y at-il un moyen de faire 5 enregistrements de mov_type 1, puis 5 enregistrements de mov_type 2. La seule façon dont j'ai pensé que vous pouvez le faire est, exécuter 2 requêtes et utiliser UNION pour les assembler. Je veux toujours avoir 10 résultats si possible ... et si une recherche donne 1 film (mov_type = 1) et 14 émissions de télévision (mov_type = 2), en utilisant UNION cela donnera 6 enregistrements (puisque je ferais LIMIT 5 sur chaque requête), au lieu de 10 (1 film, et 9 émissions télévisées).

Toute autre façon que je peux faire cela?

+0

La plupart de vos les questions n'ont pas de réponses acceptées, pouvez-vous y travailler un peu? – RedFilter

Répondre

1

Exécutez simplement deux requêtes, une pour chaque catégorie, et les deux retournent 10 éléments. Ensuite, dans votre code d'application, fusionnez-les dans une liste en fonction du nombre ou des éléments renvoyés.

1

C'est assez énorme, et probablement de meilleurs résultats si vous avez fait un peu dans la couche d'application, mais quelque chose comme ça devrait le faire:

select * from ( 
    SELECT * 
    FROM movies 
    WHERE mov_type=1 
     and mov_title LIKE '%" . $queryString . "%' 
     AND mov_status = 1 
     AND mov_incomplete = 0 
    LIMIT 5 

    UNION ALL 

    SELECT * 
    FROM movies 
    WHERE mov_type=2 
     and mov_title LIKE '%" . $queryString . "%' 
     AND mov_status = 1 
     AND mov_incomplete = 0 
    LIMIT 5 

    UNION ALL 

    SELECT * 
    FROM movies 
    WHERE mov_type=1 
     and mov_title LIKE '%" . $queryString . "%' 
     AND mov_status = 1 
     AND mov_incomplete = 0 
     AND id not in (
      SELECT id 
      FROM movies 
      WHERE mov_type=1 
       and mov_title LIKE '%" . $queryString . "%' 
       AND mov_status = 1 
       AND mov_incomplete = 0 
      LIMIT 5 
     ) 
    LIMIT 5 

    UNION ALL 

    SELECT * 
    FROM movies 
    WHERE mov_type=2 
     and mov_title LIKE '%" . $queryString . "%' 
     AND mov_status = 1 
     AND mov_incomplete = 0 
     AND id not in (
      SELECT id 
      FROM movies 
      WHERE mov_type=2 
       and mov_title LIKE '%" . $queryString . "%' 
       AND mov_status = 1 
       AND mov_incomplete = 0 
      LIMIT 5 
     ) 
    LIMIT 5 
) a 
LIMIT 10 

Ce serait une bonne idée de déplacer certains cette logique d'affaires en vue d'éviter tant la répétition, par exemple:

create view ActiveMovies as 
SELECT * 
FROM movies 
WHERE mov_status = 1 
    AND mov_incomplete = 0 

Ensuite, il ressemblerait plus:

select * from ( 
    SELECT * 
    FROM ActiveMovies 
    WHERE mov_type=1 
     and mov_title LIKE '%" . $queryString . "%' 
    LIMIT 5 

    UNION ALL 

    SELECT * 
    FROM ActiveMovies 
    WHERE mov_type=2 
     and mov_title LIKE '%" . $queryString . "%' 
    LIMIT 5 

    UNION ALL 

    SELECT * 
    FROM ActiveMovies 
    WHERE mov_type=1 
     and mov_title LIKE '%" . $queryString . "%' 
     AND id not in (
      SELECT id 
      FROM ActiveMovies 
      WHERE mov_type=1 
       and mov_title LIKE '%" . $queryString . "%' 
      LIMIT 5 
     ) 
    LIMIT 5 

    UNION ALL 

    SELECT * 
    FROM ActiveMovies 
    WHERE mov_type=2 
     and mov_title LIKE '%" . $queryString . "%' 
     AND id not in (
      SELECT id 
      FROM ActiveMovies 
      WHERE mov_type=2 
       and mov_title LIKE '%" . $queryString . "%' 
      LIMIT 5 
     ) 
    LIMIT 5 
) a 
LIMIT 10 
+0

Cela semble fonctionner. Mon seul reproche serait l'utilisation de 'not in', mais considérant que la sous-requête renvoie au plus 5 items, ce n'est pas mal. Je prendrais probablement les deux premiers "sélects" et je les rendrais "withs" à la place, pour clarifier le fait qu'ils sont réutilisés dans la partie postérieure. – krdluzni

1

Pourquoi ne pas:

SELECT * FROM (
    SELECT * FROM movies 
    WHERE mov_title LIKE '%" . $queryString . "%' 
    AND mov_status = 1 
    AND mov_incomplete = 0 
    ORDER BY mov_title 
    LIMIT 10 
) AS a 
ORDER BY a.mov_type, a.mov_title 

subselects font un problème beaucoup plus simple.

+0

Cette requête ne tente pas de renvoyer le top 5 de chaque catégorie, elle renvoie simplement les dix premiers enregistrements triés par titre, de sorte que vous pouvez obtenir 10 films lorsqu'il y a des émissions télévisées qui doivent également être renvoyées. – RedFilter

+0

Pire: En réalité, il est classé par type, donc s'il y a 10 films correspondants, vous êtes assuré de ne pas avoir de spectacle. – krdluzni

0

quelque chose comme ça devrait le faire:

SET @num:=0; SELECT *, IF (mov_type=1, @num:[email protected]+2, 11) AS num 
FROM movies 
WHERE mov_title LIKE '%" . $queryString . "%' AND mov_status = 1 AND mov_incomplete = 0 
ORDER BY num, mov_type, mov_title LIMIT 10 

modifier: En fait, il est probablement pas efficace, mais vous pouvez le combiner avec la requête syndicale, devrait être plus rapide:

SET @num:=0; 
SELECT *, IF (mov_type=1, @num:[email protected]+2, 11) AS num FROM (
    SELECT * 
    FROM movies 
    WHERE mov_type=1 
     and mov_title LIKE '%" . $queryString . "%' 
     AND mov_status = 1 
     AND mov_incomplete = 0 
    LIMIT 10 

    UNION ALL 

    SELECT * 
    FROM movies 
    WHERE mov_type=2 
     and mov_title LIKE '%" . $queryString . "%' 
     AND mov_status = 1 
     AND mov_incomplete = 0 
    LIMIT 10 
) ORDER BY num LIMIT 10; 
Questions connexes