Vous n'êtes pas identifié(e).
Bonjour tout le monde,
je n'arrive pas à créer la requête que j'aimerai, alors j'en viens à me demander si c'est possible avec la façon dont j'ai créé mes tables.
J'ai deux tables :
create table fiche(
id_user int NOT NULL,
nom varchar(30),
prenom varchar(30),
constraint fiche_pkey primary key (id_user));
create table parents(
id_parents int NOT NULL UNIQUE,
id_u int,
id_papamaman int,
constraint parents_pkey primary key (id_u,id_papamaman),
FOREIGN KEY (id_u)
REFERENCES fiche(id_user),
FOREIGN KEY (id_papamaman)
REFERENCES fiche(id_user)
En fait il y a plusieurs fiches et je crée des liens entre eux grâce à parents. Donc dans parents, id_u, va correspondre à une personne et id_papamaman à un de ses parents.
Est ce qu'il est possible de comparer le nom d'id_u et le nom d'id_papamaman?
L'une des requêtes que j'ai tapé qui pour moi ressemble le plus à ce que j'aimerai, mais qui ne me donne pas ce que j'attendais est :
SELECT *
FROM fiche
NATURAL JOIN parents
where nom =(select nom
from fiche
where id_user=id_papamaman);
Merci d'avance pour votre aide, j'ai l'impression que c'est très simple en plus
Hors ligne
C'est effectivement très compliqué pour rien, au niveau du modèle, si il n'y a que ces deux tables. Quel intérêt de ne pas stocker un id_pere et un id_mere dans la table fiche, directement, si on parle de parents biologiques ?
Sinon, pour la question, comparer id_u et id_papamaman comment ? (désolé ce n'est pas très clair, dans la question…)
Marc.
Hors ligne
En fait, c'est quelque chose qui m'est imposé de déterminer le nom du (ou des) parent(s) et enfant, pour voir s'ils ont le même.
Comparer id_u et id_papamaman par leur nom puisque ceux sont des id_user (clés étrangères)
Rajouter un champ id_pere et un champ id_mere dans la table fiche, va seulement me permettre d'avoir une table en moins(non?), pourquoi pas, mais je ne vois toujours pas comment avec cette table je peux identifier le nom du père à partir id_pere et le nom du fils à partir d' id_u puisque j'ai seulement leur numéro.
En français la requête serait :
Selectionner le nom,prenom des "id_user"
Où leur nom est égal au nom d' "id_pere" ET nom d'id_mere
J'espère que ma réponse éclaircie la situation.
Je rajoute un petit exemple
FICHE
__________________________
|id_user | nom | prenom |
|_______|__________|________|
| 1 | DUPONT | martin |
|_______|__________|________|
| 2 | DUPONT | julie |
|_______|__________|________|
| 3 | DUPONT | henry |
|_______|__________|________|
| 4 | X | nicolas |
|_______|__________|________|
| 5 | DUPONT | Sylvie |
|_______|__________|________|
PARENTS
___________________________________
|id_parents | id_u | id_papamaman |
|__________|__________|______________|
| 1 | 1 | 2 | Martin DUPONT a pour parent Julie DUPONT
|__________|__________|______________|
| 2 | 1 | 4 | Martin DUPONT a pour parent Nicolas X
|__________|__________|______________|
| 3 | 3 | 1 | Henry DUPONT a pour parent Matin DUPONT
|__________|__________|______________|
| 4 | 3 | 5 | Henry DUPONT a pour parent Sylvie DUPONT
|__________|__________|______________|
Donc j'aimerai que ma requête me sélectionne Henry DUPONT puisque ses deux parents ont le même nom que lui
Dernière modification par kiara77 (23/03/2011 10:51:35)
Hors ligne
Ok, vous voulez donc simplement comparer les noms de famille des parents et des enfants ?
Avec votre schéma actuel:
SELECT fiche_enfant.nom AS nom_enfant,
fiche_parent.nom AS nom_parent
FROM parents
JOIN fiche AS fiche_enfant ON (parents.id_u=fiche_enfant.id_user)
JOIN fiche AS fiche_parent ON (parents.id_papamaman=fiche_parent.id_user)
Si vous voulez n'avoir que ceux où les noms sont différents, il suffit de rajouter une clause WHERE:
WHERE fiche_parent.nom<>fiche_enfant.nom
Marc.
Hors ligne
Merci beaucoup, je vais étudier ça. Je ne savais pas qu'on pouvait faire plusieurs JOIN dans une même requête.
Hors ligne
Le problème serait plus simple si le modèle était correct. Et il est incorrect car il ne respecte pas les formes normales.. Il vous suffit d'ajouter une entité famille contenant les noms et d'associer la personne au bon nom de famille.
En effet dans votre modèle que se passe t-il si l'orthographe d'un nom de famille est erroné pour une personne ? Vous avez plusieurs tuples à mettre à jour (avec tous les risques que cela comporte, notamment d'en mettre à jour certains et pas d'autres, donc de générer une deuxième erreur), ce qui viole une règle fondamentale de la modélisation. Alors que dans le modèle proposé, vous n'avez plus ce contrôle à faire car le nom est toujours unique pour une même famille. Et si vous voulez le corriger il n'y a qu'une seule valeur atomique à modifier....
A +
Dernière modification par SQLpro (23/03/2011 10:58:46)
Frédéric Brouard, alias SQLpro, ARCHITECTE DE DONNÉES, Expert langage SQL
Le site sur les SGBD relationnel et langage SQL : http://sqlpro.developpez.com/
Modélisation de données, conseil, expertise, audit, optimisation, tuning, formation
* * * * * Enseignant CNAM PACA, ISEN Toulon, CESI Aix en Provence * * * * *
Hors ligne
«le nom est toujours unique pour une même famille». Même en France, je doute que ça soit vrai… d'où ma question sur la filiation biologique, d'ailleurs.
Marc.
Hors ligne
Je n'ai pas encore bien regardé le diagramme proposé, mais mon but c'est qu'il soit possible d'avoir un nom de famille différent. Comme par exemple avoir des parents qui ne soient pas mariés et l'enfant a seulement le nom du père. D'après le petit texte joint avec ce diagramme, ce n'est pas possible.
Dernière modification par kiara77 (23/03/2011 11:10:34)
Hors ligne
Et sinon la proposition de Marc Cousin, ne me convient pas parce que:
WHERE fiche_parent.nom <> fiche_enfant.nom
me renvoie en plus les personnes qui ont un parent du même nom de famille
comme par exemple si le père a le même nom que la personne X
et si la mère n'a pas le même nom que la personne X.
Le where donné est validé.
alors que je veux que celui où tous les noms sont différents.
et si j'ajoute
AND fiche_parent.nom = fiche_enfant.nom
forcément la sélection est vide...
Hors ligne
Si on reformule, ce que vous voulez, ce sont les gens qui n'ont AUCUN parent ayant le même nom de famille ?
Marc.
Hors ligne
oui c'est ça. Je suis désolée je pensais m'en sortir juste en ayant la bonne jointure et trouver le where approprié seule mais apparemment pas. C'est pour cela que je n'ai pas tout dit.
Hors ligne
Vous pouvez essayer comme ceci (non testé, bien sûr)
SELECT id_user,
nom
FROM fiche AS fiche_enfant
WHERE NOT EXISTS
(SELECT 1
FROM parents
JOIN fiche AS fiche_parent ON (parents.id_parents=fiche_parent.id_user)
WHERE fiche_enfant.id_user=parents.id_u)
Marc.
Hors ligne
ça me renvoie la liste des personnes qui n'ont pas de parents.
Je continue de faire des tests de requêtes.
ça veut dire quoi "select 1 " ?
Il n'y a aucun test dans la requête sur le nom comment vous faites pour comparer leur nom de famille ?
Dernière modification par kiara77 (23/03/2011 12:25:31)
Hors ligne
Oh, zut, un instant d'inattention et voila le résultat
SELECT id_user,
nom
FROM fiche AS fiche_enfant
WHERE NOT EXISTS
(SELECT 1
FROM parents
JOIN fiche AS fiche_parent ON (parents.id_parents=fiche_parent.id_user)
WHERE fiche_enfant.id_user=parents.id_u
AND fiche_enfant.nom=fiche_parent.nom)
En espérant ne pas avoir raté autre chose.
«SELECT 1», c'est parce que c'est un test d'existence. On veut juste savoir si la sous-requête ramène quelque chose. On se moque de ce quelque chose, tant qu'il existe. Alors autant ne pas ramener de vraies données.
Évidemment, avec cette requête, on ramène aussi ceux qui n'ont pas de parents dans la base. Vous pouvez rajouter une clause WHERE dans la requête principale pour regarder ce que vaut id_papamaman…
Dernière modification par Marc Cousin (23/03/2011 12:28:20)
Marc.
Hors ligne
ça me renvoie la liste des parents (même s'ils sont parents plusieurs, ils sont cités une fois) qu'ils aient le même nom de famille ou non que leur enfant
mais moi je cherche à avoir le nom des enfants qui n'ont pas le même nom de famille que leur parents, je pense que je le répète inutilement, vous l'avez compris
Hors ligne
Évidemment, cela vous renvoie la liste des parents. Il n'y a rien dans le modèle qui fasse la différence entre un parent et un enfant. Logiquement d'ailleurs, puisqu'un parent est aussi potentiellement l'enfant de quelqu'un d'autre.
Si vous voulez ignorer ceux qui n'ont pas de parents (et qui ne sont donc QUE parents), rajoutez une clause WHERE à la fin, comme indiqué dans le post précédent.
Quelque chose comme
AND NOT EXISTS (SELECT 1 FROM parents WHERE id_papamaman IS NULL AND parents.id_u = fiche_enfant.id_user)
Et en faisant ça, je me rends compte que ça serait certainement plus simple à écrire comme ça :
SELECT fiche_enfant.id_user,
fiche_enfant.nom
FROM fiche AS fiche_enfant
JOIN parents ON (fiche_enfant.id_user=parents.id_u)
WHERE NOT EXISTS
(SELECT 1
FROM fiche AS fiche_parent ON (parents.id_parents=fiche_parent.id_user)
WHERE fiche_enfant.nom=fiche_parent.nom)
AND parents.id_papamaman IS NOT NULL
En espérant que cette fois-ci c'est bon…
Marc.
Hors ligne
avec l'ancien code, plus la nouvelle ligne, soit :
SELECT id_user,
nom,prenom
FROM fiche AS fiche_enfant
WHERE NOT EXISTS
(SELECT 1
FROM parents
JOIN fiche AS fiche_parent ON (parents.id_parents=fiche_parent.id_user)
WHERE fiche_enfant.id_user=parents.id_u
AND fiche_enfant.nom=fiche_parent.nom
AND NOT EXISTS
(SELECT 1
FROM parents
WHERE id_papamaman IS NULL
AND parents.id_u = fiche_enfant.id_user));
j'obtiens la même solution que si je ne l'avais pas ajouté.
Et si j'utilise la version optimisée, il y a un problème au niveau du "ON"
à cette ligne
FROM fiche AS fiche_parent ON (parents.id_parents=fiche_parent.id_user)
je n'ai donc pas pu tester le code.
j'ai une petite question sur la variable "parents.id_parents" pourquoi elle n'est pas rejetée par la requête sachant que id_parents ne fait pas parti de ma table.
Hors ligne
Le NOT EXISTS ne doit pas être dans la sous-requête mais dans la requête principale.
SELECT id_user,
nom,
prenom
FROM fiche AS fiche_enfant
WHERE NOT EXISTS
(SELECT 1
FROM parents
JOIN fiche AS fiche_parent ON (parents.id_parents=fiche_parent.id_user)
WHERE fiche_enfant.id_user=parents.id_u
AND fiche_enfant.nom=fiche_parent.nom)
AND NOT EXISTS
(SELECT 1
FROM parents
WHERE id_papamaman IS NULL
AND parents.id_u = fiche_enfant.id_user);
Pour l'autre version, c'est que j'ai réécrit trop vite… oublié d'en enlever un morceau… pas pu tester… et que je suis distrait
SELECT fiche_enfant.id_user,
fiche_enfant.nom
FROM fiche AS fiche_enfant
JOIN parents ON (fiche_enfant.id_user=parents.id_u)
WHERE NOT EXISTS
(SELECT 1
FROM fiche AS fiche_parent
WHERE fiche_enfant.nom=fiche_parent.nom)
AND parents.id_papamaman IS NOT NULL
Marc.
Hors ligne
«le nom est toujours unique pour une même famille». Même en France, je doute que ça soit vrai… d'où ma question sur la filiation biologique, d'ailleurs.
Rien n'empêche cela car vous êtes libre de faire l'association que vous souhaitez entre la personne et son nom de famille !
Je n'ai pas encore bien regardé le diagramme proposé, mais mon but c'est qu'il soit possible d'avoir un nom de famille différent. Comme par exemple avoir des parents qui ne soient pas mariés et l'enfant a seulement le nom du père. D'après le petit texte joint avec ce diagramme, ce n'est pas possible.
Idem !
Frédéric Brouard, alias SQLpro, ARCHITECTE DE DONNÉES, Expert langage SQL
Le site sur les SGBD relationnel et langage SQL : http://sqlpro.developpez.com/
Modélisation de données, conseil, expertise, audit, optimisation, tuning, formation
* * * * * Enseignant CNAM PACA, ISEN Toulon, CESI Aix en Provence * * * * *
Hors ligne
Marc Cousin, la première requête renvoie la même chose, même si le AND NOT EXISTS est à l'extérieur. Et donc affiche les personnes qui n'ont pas de parents, mais les personnes qui ont seulement des parents avec le même nom de famille sont rejetées par la requête.
La deuxième requête donne un résultat.
SQLpro, je vais le regarder plus sérieusement alors.
Dernière modification par kiara77 (23/03/2011 13:28:12)
Hors ligne
SQL pro, je ne comprends pas à quoi sert T_RELATION_RLT, pourquoi veut-on avoir une date?
Dans T_LIEN_PARENTE_LPT vous avez créé un champ LPT_LIBELLE je suppose que c'est pour entrer des chaines de caractères tel que "père", "mère, "enfant"... mais où dit-on "père de quelqu'un" identifié par le PRS_ID.
Pourquoi il y a deux "lié à" ?
Est ce que le diagramme permet d'avoir des homonymes ? Je n'ai vraiment pas compris grand chose du diagramme
Hors ligne
SQLPro, je pense que l'entité famille est inutile dans votre modèle : elle ne représente rien (les relations familiales sont portées par le bas du schéma).
Sa seule fonction est de remplacer une chaîne de caractères par une clé technique... C'est probablement aussi inutile que de faire la même chose sur les prénoms, ou sur les dates de naissance. Quant à l'orthographe du nom, il est très probable qu'une erreur soit faite sur le nom d'une personne : par exemple 'Dupont' à la place de 'Dupond'. Et lorsqu'on corrige le nom de Jean, on ne veut pas modifier du même coup le nom de Jacques, qui doit rester 'Dupont'. Je ne parle même pas des noms étrangers qui sont transcrits différemment selon l'officier d'Etat Civil...
Enfin bref cela complique seulement les choses (travail de conception et de développement plus compliqué et plus risqué, jointures supplémentaires...). Pour quel gain?
De plus, on n'a pas besoin de cela pour être en 3ème forme normale : L'attribut nom dépend bien uniquement de la personne.
Hors ligne
kiara: depuis le début, j'essaye d'écrire une requête retournant les gens qui n'ont pas de parent ayant le même nom de famille… alors que ce que vous souhaitez est d'avoir les gens dont tous les parents ont le même nom de famille que lui, donc l'inverse… ça m'apprendra à lire correctement les exemples
On réessaye donc…
SELECT fiche_enfant.id_user,
fiche_enfant.nom
FROM fiche AS fiche_enfant
WHERE NOT EXISTS -- Il n'a pas de parent avec un nom différent
(SELECT 1 FROM parents JOIN fiche AS fiche_parent ON (parents.id_papamaman=fiche_parent.id_user)
WHERE fiche_enfant.id_user=parents.id_u
AND fiche_enfant.nom<>fiche_parent.nom)
AND EXISTS -- Il a quand même un parent
(SELECT 1 FROM parents
WHERE fiche_enfant.id_user=parents.id_u
)
En espérant ne pas m'être planté cette fois-ci
Marc.
Hors ligne
c'est exactement ça j'ai les personnes qui ont le même nom de famille que leur deux parents. MERCI
par contre si j'enlève le "not" de WHERE NOT EXISTS -- Il n'a pas de parent avec un nom différent
je n'obtiens pas la sélection
"les personnes qui ont un nom de famille différent de chacun de leur parent"
Si la personne a un parent avec le même nom de famille et un parent qui n'a pas le même, cela passera.
Pourquoi en enlevant seulement le not je n'obtiens pas l'inverse de la requête ?
c'est parce que la requête devient " il a au moins un parent avec un nom différent" et que la partie "ET le nom ne doit pas être égal au nom de famille d'un parent" n'est pas inclus ?
Dernière modification par kiara77 (23/03/2011 14:59:26)
Hors ligne
J'ai laissé le NOT et changé
AND fiche_enfant.nom <> fiche_parent.nom) en
AND fiche_enfant.nom = fiche_parent.nom)
ce qui donne :
SELECT fiche_enfant.id_user,
fiche_enfant.nom
FROM fiche AS fiche_enfant
WHERE NOT EXISTS -- Il n'a pas de parent avec un nom différent
(SELECT 1 FROM parents JOIN fiche AS fiche_parent ON (parents.id_papamaman=fiche_parent.id_user)
WHERE fiche_enfant.id_user=parents.id_u
AND fiche_enfant.nom = fiche_parent.nom)
AND EXISTS -- Il a quand même un parent
(SELECT 1 FROM parents
WHERE fiche_enfant.id_user=parents.id_u
)
C'est ce que je voulais pouvoir faire dans ma demande du message précédent.
Merci beaucoup ! !!
(Il n'y a rien pour dire que le sujet est résolu ? )
Dernière modification par kiara77 (23/03/2011 15:06:20)
Hors ligne