web-dev-qa-db-fra.com

Utilisation incorrecte de UNION et ORDER BY?

comment puis-je utiliser union et order by dans mysql?

select * from _member_facebook 
inner join _member_pts 
ON _member_facebook._fb_owner=_member_pts._username 
where _member_facebook._promote_point = 9 
ORDER BY Rand() limit 2 
UNION ALL
select * from _member_facebook 
inner join _member_pts 
ON _member_facebook._fb_owner=_member_pts._username 
where _member_facebook._promote_point = 8 limit 3

donne moi une erreur 

#1221 - Incorrect usage of UNION and ORDER BY

quelqu'un peut aider?

50
Yuda Prawira

Essayez avec:

(
  select 
    * 
  from 
     _member_facebook 
   inner join 
     _member_pts 
   ON 
     _member_facebook._fb_owner=_member_pts._username 
  where 
    _member_facebook._promote_point = 9 
  ORDER BY Rand() 
  limit 2
) 
UNION ALL
(
  select 
    * 
  from 
    _member_facebook 
   inner join 
    _member_pts 
   ON 
     _member_facebook._fb_owner=_member_pts._username 
  where 
    _member_facebook._promote_point = 8 
  limit 3
)

Bien que, je pense que vous devriez mettre la clause ORDER BY à la fin de la deuxième requête

72
Tudor Constantin

Avec des parenthèses:

(
    SELECT *
    FROM _member_facebook
    INNER JOIN _member_pts
    ON _member_facebook._fb_owner         =_member_pts._username
    WHERE _MEMBER_FACEBOOK._PROMOTE_POINT = 9
    ORDER BY Rand()
    LIMIT 2
)
UNION ALL
(
    SELECT *
    FROM _MEMBER_FACEBOOK
    INNER JOIN _MEMBER_PTS
    ON _MEMBER_FACEBOOK._FB_OWNER         =_MEMBER_PTS._USERNAME
    WHERE _MEMBER_FACEBOOK._PROMOTE_POINT = 8
    LIMIT 3
)

Cela dit, il n'est pas obligatoire pour MySQL de conserver le tri interne dans la clause externe, bien que probablement le fasse car il doit quand même trier les lignes pour calculer les clauses LIMIT correspondantes.

28
Álvaro González

Explication:

Il est important de comprendre comment cela fonctionne pour éviter les "pièges" dans des cas d'utilisation similaires. Notez que la syntaxe de union est quelque peu "spéciale":

substatement union all substatement union all substatement [Clause order by] [Clause limit]

où "substatement" peut éventuellement être entouré de ( et ). Quelques exemples de travail:

  • select 1 union all (select 2);
    select 1 union all  select 2  union all (select 3);
    select 1 union all (select 2) union all  select 3;
    select 1 union all (select 2) union all (select 3);
    select 1 union all (select 2) union all (select 3) union all  select 4;
    select 1 union all (select 2) union all  select 3  union all (select 4);
    

Cependant, si vous entourez le premier "substatement" avec des accolades, vous devez entourez tous les autres "substatement} _" avec des accolades:

  • (select 1) union all (select 2) union all (select 3);
    

(Notez que le point ci-dessus n’est pas mentionné dans la documentation officielle .)

Ne pas le faire est une erreur de syntaxe:

  • mysql> (select 1) union all select 2; -- error because not all "substatement"s are braced
    ERROR 1064 (42000): You have an error in your SQL syntax; check the...
    mysql> (select 1) union all (select 2) union all  select 3; -- error because not all "substatement"s are braced
    ERROR 1064 (42000): You have an error...
    mysql> (select 1) union all  select 2  union all (select 3); -- error because not all "substatement"s are braced
    ERROR 1064 (42000): You have an error...
    

Ensuite, chaque "substatement} _" peut contenir where, group by, having, join, limit, mais pas order by

Si vous souhaitez utiliser order by, le "substatement" qui contient order by doit être entouré d'accolades. (Ce qui signifie qu'ils ne sont plus facultatifs.)

Maintenant, si nous examinions à nouveau la syntaxe:

substatement union all substatement union all substatement [Clause order by] [Clause limit]

nous pouvons voir que l'instruction union entière se termine par un order bylimit facultatif. Ces deux mots clés s'appliquent à la totalité de l'instruction union, et pas seulement au dernier "substitution":

  • mysql> select 1
        -> union all
        -> select 2 limit 1;
    +---+
    | 1 |
    +---+
    | 1 |
    +---+
    1 row in set (0.00 sec)
    
    mysql>
    

Nous avons déjà mentionné que le mot clé limit peut également être appliqué à des "substatement}" individuels:

  • mysql> select 1 limit 1
        -> union all
        -> select 2;
    +---+
    | 1 |
    +---+
    | 1 |
    | 2 |
    +---+
    2 rows in set (0.00 sec)
    
    mysql>
    

Si vous souhaitez appliquer limit au dernier "substatement}" (par opposition à la totalité de l'instruction union), vous _/devez entourez le dernier "substatement" avec des accolades:

  • mysql> select 1
        -> union all
        -> (select 2 limit 1);
    +---+
    | 1 |
    +---+
    | 1 |
    | 2 |
    +---+
    2 rows in set (0.00 sec)
    
    mysql>
    

Pour appliquer limit au dernier "substatement" et à la totalité de l'instruction union, utilisez:

  • mysql> select 1
        -> union all
        -> (select 2 limit 1)limit 1;
    +---+
    | 1 |
    +---+
    | 1 |
    +---+
    1 row in set (0.00 sec)
    
    mysql>
    

C'est pareil avec order by:

  • mysql> select 1
        -> union all
        -> (select 2 order by 1)order by 1;
    +---+
    | 1 |
    +---+
    | 1 |
    | 2 |
    +---+
    2 rows in set (0.00 sec)
    
    mysql>
    

Mais notez que l'application de order by à "substatement" s est sans signification car les documents ont explicitement déclaré que order by n'est garanti ( cf. ) que lorsque appliqué à l'ensemble de l'instruction union:

–§– .. L'utilisation de ORDER BY pour des instructions SELECT individuelles n'implique en aucun cas l'ordre dans lequel les lignes apparaissent dans le résultat final.

La seule façon dont order by aurait du sens dans un "substatement} _" est si vous le combinez avec limit:

–§– ... l'utilisation de ORDER BY dans ce contexte est généralement associée à LIMIT, de sorte qu'elle est utilisée pour déterminer le sous-ensemble des lignes sélectionnées à extraire pour SELECT, même si affecte nécessairement l'ordre de ces lignes dans le résultat final UNION.

De plus, si vous voulez combiner select into avec union, vous aurez plus de "pièges" à surveiller. Voir numéro 32858 à ce sujet.

22
Pacerier

try () je pense comme

(SELECT  CITY,LENGTH(CITY) FROM STATION WHERE LENGTH(CITY)=(SELECT MIN(LENGTH(CITY)) FROM STATION) ORDER BY CITY LIMIT 1) 
UNION ALL
(SELECT  CITY,LENGTH(CITY) FROM STATION WHERE LENGTH(CITY)=(SELECT MAX(LENGTH(CITY)) FROM STATION) ORDER BY CITY LIMIT 1);
0
anil kumar meena

Je pense que l’utilisation de parenthèses est obligatoire si vous utilisez ordre ou limite ou les deux. J'ai essayé de travailler sur une requête en utilisant limit et order de manière interchangeable sans parenthèse et la requête ne fonctionnait pas. Cela n'a fonctionné qu'après avoir ajouté une parenthèse.

0
Syed Quader

Le correct est:

(SELECT *
   FROM _member_facebook
   INNER JOIN _member_pts ON _member_facebook._fb_owner=_member_pts._username
   WHERE _member_facebook._promote_point = 9 LIMIT 2)
UNION ALL
  (SELECT *
   FROM _member_facebook
   INNER JOIN _member_pts ON _member_facebook._fb_owner=_member_pts._username
   WHERE _member_facebook._promote_point = 8 LIMIT 3)
ORDER BY 1