Requête qui cherche plusieurs valeurs simultanément

Requête qui cherche plusieurs valeurs simultanément - SQL/NoSQL - Programmation

Marsh Posté le 19-08-2005 à 03:00:54    

Salut tout le monde,
 
Je dois faire une requête simple au premier abors mais qui me pose un problème au second :D (ché pas si ça se dit)
 
Pour ce faire, mettons-nous en situation ^^
 
- J'ai une table SALARIE avec tous les champs traditionnel
- J'ai une table VACUITE qui enregistre les mois pendant lesquels les salariés sont librent qui est composée de v_salarie (id du salarié) et v_mois (num du mois de l'année)
 
But du jeu, dans un formulaire php, l'utilisateur va cocher des mois et en validant le formulaire, la liste des salariés librent ces mois là doit s'afficher.
 
Voilà où j'en suis. Mon code php me génère une requête du genre :
 
SELECT s_nom, s_prenom FROM salarie, vacuite WHERE v_mois IN (4, 5, 6) AND s_id = v_salarie GROUP BY s_id ORDER BY s_nom;
 
A priori pour moi ça veut dire, récupère-moi les noms, prénoms des salariés dont les mois de vacuité se trouvent dans 4, 5, 6.
 
Bon ça marche mais y'a un problème, il me sort aussi les salariés librent avec chacune des combinaisons des 3 mois. Ce que je voudrai, c'est qu'il me sort que les salariés qui sont librent ces trois mois et pas uniquement l'un des trois ni deux des trois. Vous voyez de quoi je parle ?
 
Mon objectif à terme, est de monter une sorte de moteur de recherche qui peut porter sur d'autres critères qui ont la même architecture. A savoir par exemple pour des critères concernant les diplômes des salariés, j'ai une table avoir_diplome avec 2 champs ad_salarie et ad_diplome qui sont à chaque fois des identifiants.
 
Aidez-moi siouplé je sais pas dans quel sens prendre ça :(

Reply

Marsh Posté le 19-08-2005 à 03:00:54   

Reply

Marsh Posté le 19-08-2005 à 11:41:19    

mySql ? Possibilité de faire des sous-requêtes ?
 
Si ce n'est pas possible, il faudra récupérer la liste des id des personnes libres tous ces mois, puis récupérer les noms.
 

Code :
  1. SELECT s_id
  2. FROM vacuite
  3. WHERE v_mois IN (4, 5, 6)
  4. GROUP BY s_id
  5. HAVING COUNT(*) = 3;


 
Puis :
 

Code :
  1. SELECT s_nom, s_prenom
  2. FROM salarie
  3. WHERE s_id IN (<liste des s_id de la première requête> )
  4. ORDER BY s_nom, s_prenom;


 
Sinon, tu peux utiliser une table temporaire pour le résultat de la première requête.
 
Si tu peux utiliser des sous-requêtes, je te laisse combiner les 2 ...

Reply

Marsh Posté le 19-08-2005 à 12:21:42    

Je pense qu'on peut tout faire d'un coup [:figti]  
 
SELECT s_nom, s_prenom, COUNT(*) AS c
FROM salarie, vacuite  
WHERE v_mois IN (4, 5, 6) AND s_id = v_salarie GROUP BY s_id  
ORDER BY s_nom
HAVING c=3

Reply

Marsh Posté le 19-08-2005 à 13:26:20    

Ca dépend des SGBD, il me semble que ça marche pas sous Oracle par exemple, car il faudrait sélectionner les champs sur lesquels on groupe (et le COUNT(*) si on veut).

Reply

Marsh Posté le 19-08-2005 à 13:58:26    

Merci pour vos réponses. J'utilise MySQL en effet. Vos propositions semblent répondre au problème. En supposant que cela fonctionne, comment dois-je modifier cette requête pour étendre la restriction à d'autres critères, par exemple les diplômes.
 
SELECT s_nom, s_prenom, COUNT(*) AS c
FROM salarie, vacuite, avoir_diplome
WHERE v_mois IN (4, 5, 6) AND s_id = v_salarie AND ad_diplome IN (2, 10, 11) AND s_id = ad_salarie GROUP BY s_id  
ORDER BY s_nom
HAVING c=3  
 
Vous pensez que ça va prendre en compte les salariés qui possèdent les diplômes 2, 10 et 11 ?


Message édité par Inekman le 19-08-2005 à 13:58:57
Reply

Marsh Posté le 19-08-2005 à 14:04:07    

Ca marchera pas, tu comptes le nombre total de lignes renvoyées par les jointures ... En réalité, il faudrait que le COUNT(*) soit égal à (nombre de mois) * (nombre de diplômes), soit 9 dans ce cas précis ...
 
Sinon tu peux casser en plusieurs requêtes, une pour récupérer les ids de ceux qui sont libres sur les mois choisis, puis une autre pour récupérer les ids de ceux qui ont les diplômes choisis, tu fais l'intersection dans le code PHP, et enfin tu récupères les infos (noms / prénoms) des personnes qui correspondent.

Reply

Marsh Posté le 19-08-2005 à 14:08:36    

Donc je fais à chaque fois une requête pour chaque critères que je souhaite prendre en compte et à la fin, je prend juste les salariés qui se trouvent dans chacun des résultats retournés, c'est à dire ceux qui ont répondu à tous les critères.
 
Je vais voir ça, merci beaucoup pour votre aide les gars ;-)

Reply

Marsh Posté le 19-08-2005 à 14:10:37    

C'est en effet un moyen simple de le faire.
Si tu as une version de mySql récente, qui permet les sous-requêtes, tu peux faire bien mieux (tout en une seule requête).

Reply

Marsh Posté le 19-08-2005 à 15:09:54    

Voilà ma version de Mysql : 4.1.10a-nt - extension : mysqli
 
Tu peux m'en dire plus sur la technique all-in-one ? :)

Reply

Marsh Posté le 19-08-2005 à 15:37:08    

Apparemment les sous-requêtes devraient marcher, donc essaye quelque chose comme :
 

Code :
  1. SELECT s.s_nom, s.s_prenom
  2. FROM salarie s,
  3.      (SELECT   v_salarie
  4.       FROM     vacuite
  5.       WHERE    v_mois IN (4, 5, 6)
  6.       GROUP BY v_salarie
  7.       HAVING   COUNT(*) = 3) sub1,
  8.      (SELECT   ad_salarie
  9.       FROM     avoir_diplome
  10.       WHERE    ad_diplome IN (2, 10, 11)
  11.       GROUP BY ad_salarie
  12.       HAVING   COUNT(*) = 3) sub2
  13. WHERE    s.s_id = sub1.v_salarie
  14. AND      s.s_id = sub2.ad_salarie
  15. ORDER BY s.s_nom, s.s_prenom;


Message édité par Beegee le 19-08-2005 à 15:37:38
Reply

Marsh Posté le 19-08-2005 à 15:37:08   

Reply

Marsh Posté le 21-08-2005 à 23:11:00    

Bonsoir Beegee, je passe pour voir remercier ENORMEMENT car non seulement cela fonctionne PARFAITEMENT mais en plus, j'ai réussi à l'étendre comme un grand à d'autres critères qui se trouvent dans ma base de données.
 
Donc je tenais à vous remercier d'avoir pris ces quelques minutes à m'aider ;)
 
Voilà, encore merci.

Reply

Marsh Posté le 22-08-2005 à 00:40:47    

De rien, bonne nuit ;)

Reply

Sujets relatifs:

Leave a Replay

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