MySQL UNION imbriquée

MySQL UNION imbriquée - SQL/NoSQL - Programmation

Marsh Posté le 05-08-2008 à 16:29:33    

Hello,
 
comment faire pour qu'une telle requête fonctionne ?

 (SELECT f.AC FROM familyA f WHERE f.AC='TF105322')
UNION DISTINCT
  (SELECT f.AC FROM familyA f WHERE f.AC='tf105351')
UNION DISTINCT
    ((SELECT f.AC FROM familyA f WHERE MATCH (f.NAME, f.SYNONYM, f.DESC) AGAINST ('+muscle*' IN BOOLEAN MODE))
  UNION DISTINCT
    (SELECT f.AC FROM familyA f, genes g WHERE MATCH (g.DESC, g.SYMBOL, g.TID, g.GID) AGAINST ('+muscle*' IN BOOLEAN MODE)) ORDER BY f.AC)
UNION DISTINCT
  (SELECT f.AC FROM familyA f WHERE f.AC='Tf105323')


 
C'est un dire un sous-UNION dans un UNION ?
Est-ce possible ?
 
Merci

Reply

Marsh Posté le 05-08-2008 à 16:29:33   

Reply

Marsh Posté le 05-08-2008 à 16:33:45    

C'est quoi l'intérêt de mettre un UNION dans un UNION ? (que veux-tu faire exactement ?)


---------------
Feedback : http://forum.hardware.fr/hfr/Achat [...] 2666_1.htm
Reply

Marsh Posté le 05-08-2008 à 16:34:59    

L'intérêt c'est de conserver l'ordre.

Reply

Marsh Posté le 05-08-2008 à 16:37:02    

josiasseb a écrit :

L'intérêt c'est de conserver l'ordre.


Et si tu mets les UNION les uns en dessous des autres, ca ne conserve pas l'ordre ?


---------------
Feedback : http://forum.hardware.fr/hfr/Achat [...] 2666_1.htm
Reply

Marsh Posté le 05-08-2008 à 16:42:30    

Je veux en fait que sur le "sous-UNION" s'applique le ORDER BY, et pas sur l'ensemble.
Et que s'affiche le 1er SELECT, le 2eme, l'ensemble trouvé par la recherche fulltext, puis le dernier SELECT

Reply

Marsh Posté le 05-08-2008 à 16:44:22    

1/ vire tes "DISTINCT", le "UNION" fait un distinct implicite (cf. norme SQL92)
2/ si tu veux contrôler l'ordre, c'est pas en bidouillant avec les UNION, qui, à cause du DISTINCT justement, ne garantissent absolument pas l'ordre :
 
table T1 :


A    B
------
1    1
1    2
3    3


 
Table T2


A    B
------
2    2
1    2


 
tu fais ça :
 

Code :
  1. SELECT a, b FROM t1
  2. union
  3. SELECT a, b FROM t2


 
Vas-t-il te retourner :


1    1
1    2
3    3
2    2


ou


1    1
3    3
1    2
2    2


ou


1    1
1    2
2    2
3    3


?
 
t'en sais ABSOLUMENT rien, la norme SQL92 n'impose aucune règle.
 
chacun des trois résultats suis sa logique : le premier ne conserve que la première occurence de chaque sous-requête, le second ne conserve que les deniers, quand à la dernier, il effectue un tri avant de supprimer les doublons
 
BREF
 

Code :
  1. SELECT champA, champB, ...
  2. FROM
  3. (
  4.   SELECT requête1
  5.   union
  6.   SELECT requête2
  7.   union
  8.   ..
  9. )
  10. ORDER BY champ1, champ2, etc.


 
si tu veux gérer à la main l'ordre, tu peux ajouter une constante dans un champ bidon dans tes sous-select. par contre, ça va garantir l'unicité des résultats, donc il faudra faire des UNION ALL, qui seront infiniment plus rapide que des UNION classiques
 

Code :
  1. SELECT champA, champB, ...
  2. FROM
  3. (
  4.   SELECT 'a' ori, champA, champB FROM t1
  5.   union ALL
  6.   SELECT 'b' ori, champA, champB FROM t2
  7.   union ALL
  8.   SELECT 'c' ori, champA, champB FROM t3
  9. )
  10. ORDER BY ori

Reply

Marsh Posté le 05-08-2008 à 16:45:10    

ps : et je sais que ça ne répond pas exactement à ta question. maintenant à toi d'adapter ton problème avec cette piste.

Reply

Marsh Posté le 05-08-2008 à 16:51:01    

Je veux garder l'ordre mais les DISTINCT aussi.
 
Affichage du 1er SELECT, du 2eme si différent du 1er, ...

Reply

Marsh Posté le 05-08-2008 à 17:05:52    

à moins de sortir une mysqlbidouille, tu ne peux pas
 
le modèle n'est pas une information, tu n'as donc pas à savoir d'où vient une donnée à la sortie d'une requête. c'est un des fondements des SGBD. donc pas d'order possible en fonction de la table, et encore moins "garder la ligne d'une table plutôt que d'une autre"
 
tu peux toujours t'en sortir en faisant une usine à gaz à grands coups de not in () et en conservant le préfixe comme j'ai indiqué : tu sélectionnes tout select 't1' ori, * from t1 union all select 't2' ori, * from t2 where id not exists (select id from t1) order by ori
 
m'enfin avec la chiée d'union, si tu fous pas à genoux le serveur, t'auras beaucoup de chance


Message édité par MagicBuzz le 05-08-2008 à 17:08:00
Reply

Marsh Posté le 05-08-2008 à 17:09:27    

y'a une solution aussi à base de left outer join à la queue leue leue, et en jouant avec des case when, m'enfin là ça va devenir franchement imbittable (ceci dit, ça devrait être performant)


Message édité par MagicBuzz le 05-08-2008 à 17:09:55
Reply

Marsh Posté le 05-08-2008 à 17:09:27   

Reply

Marsh Posté le 05-08-2008 à 17:11:54    

MB> pas besoin de left à mon avis :o
Bon ok y'a un scan de toute la table mais je suis pas sur que ça soit moins performant que ces multiples unions.

Code :
  1. SELECT
  2.  f.AC,
  3.  case when f.AC='TF105322' then 1
  4.  case when f.AC='tf105351' then 2
  5.  case when MATCH (f.NAME, f.SYNONYM, f.DESC) AGAINST ('+muscle*' IN BOOLEAN MODE)) then 3
  6.  case when MATCH (g.DESC, g.SYMBOL, g.TID, g.GID) AGAINST ('+muscle*' IN BOOLEAN MODE)) then 4
  7.  case when f.AC='Tf105323' then 5
  8.  else 0
  9.  end AS priorite
  10. FROM
  11. familyA f
  12. WHERE priorite > 0
  13. ORDER priorite ASC, f.AC


Message édité par anapajari le 05-08-2008 à 17:12:46

---------------
Software and cathedrals are much the same - first we build them, then we pray.
Reply

Marsh Posté le 05-08-2008 à 17:19:40    

je pige pas trop, parceque ça fait pas le distinct là :o
 
ceci dit, effectivement, je préfère ton écriture par rapport à l'écriture originale (en fait, j'avais même pas lu la requête, je m'étais arrêté à la structure et le order by placé à tord au milieu d'une série de union ;))

Message cité 1 fois
Message édité par MagicBuzz le 05-08-2008 à 17:20:45
Reply

Marsh Posté le 05-08-2008 à 17:33:00    

J'ai comme impératif de conserver l'ordre que fournisse les utilisateurs.
Un ordre pas toujours bien éclairé, c'est le pourquoi des DISTINCT, et de certains contrôles au préalable.
 
En mettant un ORDER BY dans chacun des fulltext, ça fonctionne.

Reply

Marsh Posté le 06-08-2008 à 09:24:27    

MagicBuzz a écrit :

je pige pas trop, parceque ça fait pas le distinct là :o
ceci dit, effectivement, je préfère ton écriture par rapport à l'écriture originale (en fait, j'avais même pas lu la requête, je m'étais arrêté à la structure et le order by placé à tord au milieu d'une série de union ;))


J'avais pas vu le distinct :o
Mais bon suffit de mettre un "select distinct" du coup  
 

josiasseb a écrit :

J'ai comme impératif de conserver l'ordre que fournisse les utilisateurs.
Un ordre pas toujours bien éclairé, c'est le pourquoi des DISTINCT, et de certains contrôles au préalable.
En mettant un ORDER BY dans chacun des fulltext, ça fonctionne.


Nan mais les distinct je comprends vaguement leur utilisation. Par contre faire 4 unions de select qui sont tous sur la même table je comprends moins, même si niveau perf il ne doit pas y avoir de grosse différence.
 


---------------
Software and cathedrals are much the same - first we build them, then we pray.
Reply

Marsh Posté le 06-08-2008 à 16:26:18    

Je n'ai pas le ORDER BY combiné sur mes deux recherches fulltext mais les performances sont assez bonnes.
 
Donc, satisfait pour l'instant.
Mais je vais regarder du coté des pistes que vous m'avez donné.
 
Merci

Reply

Marsh Posté le 07-08-2008 à 12:52:42    

j'avais un problème similaire va voir ici :  
http://forum.hardware.fr/forum2.ph [...] w=0&nojs=0
 

Reply

Marsh Posté le 07-08-2008 à 14:18:26    

Je suis arrivé à peu prêt à la même conclusion, à savoir enchainer les UNION pour conserver l'ordre de mes requêtes.
 
Je fais un ORDER BY sur chacune de mes 2 recherches fulltext, au lieu d'un ORDER BY sur l'ensemble des 2 requêtes fulltext.
J'obtiens quasiment ce que je veux mais j'aurais préféré avoir un seul ORDER BY par groupe de recherches fulltext.

Reply

Marsh Posté le 08-08-2008 à 10:23:44    

Oui mais ça c'est pas possible..

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed