Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1795 connectés 

  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  intersection d'ensembles?

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

intersection d'ensembles?

n°2240806
antiseptiq​ueincolore
Posté le 20-10-2014 à 19:47:45  profilanswer
 

Bonjour,
alors je sais qu'on ne répond pas aux demandes de résolutions d'exos, mais ça n'est pas mon exo, et je ne dois le rendre à personne  :o  
mais si ça ne va pas, on ferme et puis c'est tout.
 
Le pdf d'exos est ici
http://cedric.cnam.fr/~crucianm/src/ED-SQL.pdf
c'est l'exo 3, la question 7. Je sèche
Qui a reçu tous les cadeaux qu'il avait souhaité?
Je vois bien que pour chaque personne, l'ensemble des cadeaux reçus doit contenir l'ensemble des cadeaux demandés, mais je ne vois pas comment l'écrire
 
Si vous avez une idée, ça me permettra de comprendre, merci

mood
Publicité
Posté le 20-10-2014 à 19:47:45  profilanswer
 

n°2240811
gpl73
Posté le 20-10-2014 à 22:22:35  profilanswer
 

Salut !
dans ta question 7 :
Qui a reçu tous les cadeaux qu'il avait souhaité ?
tu as deux tables, où tu as les informations correspondantes :
SOUHAIT (n°personne, âge_anniversaire, cadeau)
OFFERT (n°personne offrant, n°personne recevant, âge_anniversaire, cadeau)

 

select a.n°personne ,count(distinct a.cadeau)), count(distinct (b.cadeau))
from souhait as a inner join offetr as b
on a.n°personne = b.n°personne recevant
and a.cadeau = b.cadeau
(and a.age_anniversaire = b.age_anniversaire à voir, c'est pas dit dans l'énoncé))
where count(distinct a.cadeau)) = count(distinct (b.cadeau))
group by a.n°personne (ajouté a.age_anniversaire)

 

A voir pour la syntaxe, car elle est faite comme ça sans avoir de sql sous la main :)

 

Guillaume


Message édité par gpl73 le 20-10-2014 à 22:43:06

---------------
mieux vaut être un con au chaud, qu'un con gelé lol
n°2240822
antiseptiq​ueincolore
Posté le 21-10-2014 à 09:13:56  profilanswer
 

Merci d'y avoir passé un peu de temps!
Non, ça ne marche pas. Au cas où, je suis sous mysql.
 
Le problème vient que :

Code :
  1. where count(distinct a.cadeau) = count(distinct b.cadeau)


il n'en veut pas.
 
Si je remplace par

Code :
  1. HAVING COUNT( DISTINCT a.cadeau ) = COUNT( DISTINCT b.cadeau)


ça passe, mais c'est faux puisque cette condition est toujours vraie puisque c'est une condition de la jointure (si je ne dis pas de betise)
Donc je me retrouve avec tous la liste de toutes les personnes


Message édité par antiseptiqueincolore le 21-10-2014 à 09:15:08
n°2240829
antiseptiq​ueincolore
Posté le 21-10-2014 à 10:27:51  profilanswer
 

Merci, je crois que j'ai un truc qui a l'air de fonctionner  :jap:  

Code :
  1. select DISTINCT nom
  2. from SOUHAIT
  3. where nom NOT IN(
  4.    select DISTINCT a.nom
  5.    from SOUHAIT as a left join OFFERT as b
  6.    on a.nom = b.nom
  7.    and a.cadeau = b.cadeau
  8.    where b.cadeau IS NULL)


Message édité par antiseptiqueincolore le 21-10-2014 à 10:31:13
n°2240832
rufo
Pas me confondre avec Lycos!
Posté le 21-10-2014 à 10:57:20  profilanswer
 

Pour rappel, les fonctions d’agrégation (comme count, max, sum...) ne se mettent pas dans le WHERE mais dans le SELECT. Dans le HAVING, c'est possible aussi mais tu peux t'en passer en mettant des alias aux count() du select et en utilisant ces alias dans le having ;)


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2240847
antiseptiq​ueincolore
Posté le 21-10-2014 à 13:00:55  profilanswer
 

je comprends pas

n°2240850
rufo
Pas me confondre avec Lycos!
Posté le 21-10-2014 à 13:13:26  profilanswer
 

C'était pour expliquer pourquoi le count() (qui est une fonction d'agrégation) placé dans la clause WHERE ne fonctionnait pas ;)
 
Pour le having, je voulais juste dire qu'on pouvait utiliser les alias comme ceci :
SELECT nom, count(a.cadeau) as NB_Cadeaux1, count(b.cadeau) as NB_Cadeaux2 FROM ... WHERE... GROUP BY nom HAVING NB_Cadeaux1 = NB_Cadeaux2


Message édité par rufo le 21-10-2014 à 13:13:44

---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2240871
lasnoufle
La seule et unique!
Posté le 21-10-2014 à 15:16:12  profilanswer
 

Salut

 

Sinon antiseptiqueindolore, l'exo est egalement "faisable" en utilisant des counts() comme tu essayais de le faire initialement, il faut juste jouer un peu avec la structure de la requete et c'est pas vraiment intuitif :D.
Celle-ci devrait marcher:

SELECT p.nom, p.prenom
FROM personnes p
JOIN (SELECT s.nopersonne, count(s.cadeau) as nb_souhaits
      FROM souhait s
      GROUP BY s.nopersonne) shs ON shs.nopersonne = p.nopersonne
JOIN (SELECT o.nopersonne_recevant, count(o.cadeau) as nb_recus
      FROM offert o
      GROUP BY o.nopersonne_recevant) rcs ON rcs.nopersonne_recevant = p.nopersonne
WHERE rcs.nb_recus = shs.nb_recus

Cependant attention: ca ne marche que si les cadeaux offerts sont forcement pris parmi les cadeaux souhaites. L'exercice ne precise pas. Mais si par exemple Robert veut un chou et que Roger lui offre une carotte, la requete au-dessus ne marche plus et doit etre "amelioree":

SELECT p.nom, p.prenom
FROM personnes p
JOIN (SELECT s.nopersonne, count(s.cadeau) as nb_souhaits
      FROM souhait s
      GROUP BY s.nopersonne) shs ON shs.nopersonne = p.nopersonne
JOIN (SELECT o.nopersonne_recevant, count(o.cadeau) as nb_recus
      FROM offert o
      JOIN souhait s ON s.nopersonne = o.nopersonne_recevant AND s.cadeau = o.cadeau
      GROUP BY o.nopersonne_recevant) rcs ON rcs.nopersonne_recevant = p.nopersonne
WHERE rcs.nb_recus = shs.nb_recus

Au final ca reste un peu plus complique que ta propre solution, mais ca reste possible.

 

Pour finir, tu peux essayer un truc comme ca mais de tete je doute que ca marche (j'ai rien de lance pour verifier la maintenant):

SELECT p.nopersonne, p.nom, p.prenom
FROM personnes p
JOIN souhait s ON s.nopersonne = p.nopersonne
GROUP BY p.nopersonne, p.nom, p.prenom
HAVING (p.nopersonne, COUNT(s.cadeau)) = (SELECT o.nopersonne_recevant, count(o.cadeau)
                                          FROM offert o
                                          JOIN souhait s ON s.nopersonne = o.nopersonne_recevant AND s.cadeau = o.cadeau
                                          WHERE o.nopersonne_recevant = p.nopersonne
                                          GROUP BY o.nopersonne_recevant)


L'idee est "claire" mais de tete je me souviens pas si en SQL on peut utiliser des fonctions non-agregees dans la clause HAVING. (Edit: et puis si le moteur etend le "scope" de p.nopersonne jusque dans la sous-requete)

 

Re-edit: j'me rends aussi compte que ta requete tout comme les miennes ne marcheront que si une personne ne souhaite un meme cadeau qu'une seule fois et n'est offert ce cadeau qu'une seule fois.
Sinon:
- Ta requete ne marche plus parce que Robert demandant une tomate 10 ans de suite serait "couvert" par Roger lui offrant une tomate une seule fois
- La mienne ne marche plus parce que les JOINs ne font plus du "1 pour 1" et du coup ca va fausser les comptes
Bref encore un exo "mal pense" :D


Message édité par lasnoufle le 21-10-2014 à 15:30:09

---------------
C'était vraiment très intéressant.
n°2240875
antiseptiq​ueincolore
Posté le 21-10-2014 à 15:51:24  profilanswer
 

Je regarde un peu ta solution 2.
Le truc aussi c'est qu'on peut demander 2 cadeaux et en recevoir 3.
Ton JOIN c'est un INNER JOIN?

n°2240876
lasnoufle
La seule et unique!
Posté le 21-10-2014 à 16:08:52  profilanswer
 

Mh oui je sais plus, le JOIN de base, celui qui degage la personne du resultat si elle a pas de souhaits. Oui ca doit etre INNER.


---------------
C'était vraiment très intéressant.
mood
Publicité
Posté le 21-10-2014 à 16:08:52  profilanswer
 

n°2240877
rufo
Pas me confondre avec Lycos!
Posté le 21-10-2014 à 16:42:26  profilanswer
 

JOIN, dans la norme SQL, il me semble que c'est le produit cartésien, donc le CROSS JOIN dans Mysql. Le INNER JOIN, c'est l'équi-jointure.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2240878
antiseptiq​ueincolore
Posté le 21-10-2014 à 16:42:45  profilanswer
 

je capitule  [:repie] ça compile pas, et j'ai pas encore les billes pour arriver à jongler avec la syntaxe comme ça

n°2240880
lasnoufle
La seule et unique!
Posté le 21-10-2014 à 17:10:08  profilanswer
 

Roh :D
 
Du coup j'ai lance Oracle pour checker, il y a effectivement deux erreurs dans la seconde requete:
- la table PERSONNE ne prend pas de s a la fin
- la clause WHERE c'est plutot WHERE rcs.nb_recus = shs.nb_offerts
 
Sinon ca marche.
Mon test:  
- Robert veut un pacemaker pour ses 75 ans, Roger un dentier pour ses 77.
- Robert offre le dentier, youpi!
- Roger lui est un gros radin et offre une canne a la place du pacemaker
 

create table PERSONNE ("n°personne" number, "nom" varchar2(50), "prénom" varchar2(50), "date_naissance" date);
create table SOUHAIT ("n°personne" number, "âge_anniversaire" number, "cadeau" varchar2(50));
create table OFFERT ("n°personne offrant" number, "n°personne recevant" number, "âge_anniversaire" number, "cadeau" varchar2(50));
 
insert into personne("n°personne",  "nom" , "prénom" , "date_naissance" ) values(1,'Dupont','Robert',sysdate-(365*75));
insert into personne("n°personne",  "nom" , "prénom" , "date_naissance" ) values(2,'Dupond','Roger',sysdate-(365*77));
 
insert into souhait("n°personne", "âge_anniversaire", "cadeau" ) values(1,75,'Pacemaker');
insert into souhait("n°personne", "âge_anniversaire", "cadeau" ) values(2,77,'Dentier');
 
insert into offert("n°personne offrant", "n°personne recevant", "âge_anniversaire", "cadeau" ) values(1,2,77,'Dentier');
insert into offert("n°personne offrant", "n°personne recevant", "âge_anniversaire", "cadeau" ) values(2,1,75,'Canne');
 
SELECT p."nom", p."prénom"
FROM personne p
JOIN (SELECT s."n°personne", count(s."cadeau" ) as nb_souhaits
      FROM souhait s
      GROUP BY s."n°personne" ) shs ON shs."n°personne" = p."n°personne"
JOIN (SELECT o."n°personne recevant", count(o."cadeau" ) as nb_recus
      FROM offert o
      JOIN souhait s ON s."n°personne" = o."n°personne recevant" AND s."cadeau" = o."cadeau"
      GROUP BY o."n°personne recevant" ) rcs ON rcs."n°personne recevant" = p."n°personne"
WHERE rcs.nb_recus = shs.nb_souhaits;


Ca retourne bien que Roger est content (en plus d'etre radin, elle est pas belle sa vie?)
 
Edit: jai teste aussi la derniere requete avec le HAVING COUNT, ben elle marche aussi, comme quoi. (sous Oracle en tout cas)

SELECT p."n°personne", p."nom", p."prénom"
FROM personne p
JOIN souhait s ON s."n°personne" = p."n°personne"
GROUP BY p."n°personne", p."nom", p."prénom"
HAVING (p."n°personne", COUNT("cadeau" )) = (SELECT o."n°personne recevant", count(o."cadeau" )
                                          FROM offert o
                                          JOIN souhait s ON s."n°personne" = o."n°personne recevant" AND s."cadeau" = o."cadeau"
                                          WHERE o."n°personne recevant" = p."n°personne"
                                          GROUP BY o."n°personne recevant" );


Message édité par lasnoufle le 21-10-2014 à 17:20:04

---------------
C'était vraiment très intéressant.
n°2240885
antiseptiq​ueincolore
Posté le 21-10-2014 à 18:13:14  profilanswer
 

ok ta requete elle s'execute avec mysql si je mets SYSDATE() et que je respecte la casse, mais là ça doit etre un pb linux

n°2240887
lasnoufle
La seule et unique!
Posté le 21-10-2014 à 18:31:13  profilanswer
 

Ah oui effectivement mon test est sous Oracle donc il va peut-etre y avoir quelques differences de syntaxe avec MySql. Par contre je peux pas t'aider avec ca mais ca devrait pas etre insurmontable.


---------------
C'était vraiment très intéressant.
n°2240894
antiseptiq​ueincolore
Posté le 21-10-2014 à 20:16:31  profilanswer
 

rufo a écrit :

JOIN, dans la norme SQL, il me semble que c'est le produit cartésien, donc le CROSS JOIN dans Mysql. Le INNER JOIN, c'est l'équi-jointure.


 
"En l'absence d'un type de jointure explicite, la jointure sera considérée comme interne (INNER JOIN)"
 
Souhaitez moi bonne chance pour demain, je suis un expert en bases de données  :o  
 

n°2240895
gpl73
Posté le 21-10-2014 à 20:17:26  profilanswer
 

il doit y avoir un truc ! dans l'énoncé ou alors le mec c'est gourré :)
car au vue des questions précédentes lol
les solutions proposées sur carrément d'un autre niveau :)
le having de rufo, ne suffit pas?


---------------
mieux vaut être un con au chaud, qu'un con gelé lol
n°2240897
antiseptiq​ueincolore
Posté le 21-10-2014 à 20:28:33  profilanswer
 

rufo tu as une solution?
Je contacte l'auteur du sujet aussi, pour savoir ce qu'elle a pensé

n°2240899
lasnoufle
La seule et unique!
Posté le 21-10-2014 à 20:45:51  profilanswer
 

Non mais vu le reste des questions, la reponse c'est a mon avis aucune des solutions proposees ici.
 
Le NOT IN propose au debut par antiseptique fait l'affaire en gros mais vu l'imprecision du sujet je suppute fortement qu'ils attendent qu'on fasse la jointure sur age + cadeau plutot que sur seulement cadeau.
Et c'est tout.
 
Les trucs que j'ai ajoute pour montrer comment on peut faire avec count() et having c'etait juste pour montrer que c'est possible mais je doute fortement que ca soit la reponse attendue.


---------------
C'était vraiment très intéressant.
n°2241029
gpl73
Posté le 23-10-2014 à 12:35:18  profilanswer
 

antiseptiqueincolore : mets la correction, stp :)


---------------
mieux vaut être un con au chaud, qu'un con gelé lol
n°2241030
antiseptiq​ueincolore
Posté le 23-10-2014 à 12:38:06  profilanswer
 

l'auteur du sujet n'a pas répondu à mon mail, donc je n'en sais pas plus

n°2241061
Oliiii
Posté le 24-10-2014 à 08:55:52  profilanswer
 

Moi j'aurais fait ca:

Code :
  1. SELECT a.NoPersonne
  2. FROM Souhait a
  3.     LEFT JOIN Offert b ON b.NoPersonneRecevant = a.NoPersonne AND b.AgeAnniversaire = a.AgeAnniversaire AND b.Cadeau = a.Cadeau
  4. GROUP BY a.NoPersonne
  5. HAVING MAX(CASE WHEN b.NoPersonneRecevant IS NULL THEN 1 ELSE 0 END) = 0


 
Si il faut le nom, prenom il suffit de faire a join avec Personne.

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  intersection d'ensembles?

 

Sujets relatifs
[RUBY] intersection d'array[Python] intersection, combinations ?
SELECT et COUNT avec postgres avec INTERSECTIONIntersection de formes
[Flash + Sandy3D] Matérialiser intersection Plan / CylindreScheme : fonction intersection
opengl: intersection de segment en mode blend.[EXCEL/VBA] Intersection avec une courbe lissée [RESOLU]
Algo pour intersection de figuresIntersection de procedure stocke
Plus de sujets relatifs à : intersection d'ensembles?


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR