Précédent   Forum des professionnels en informatique > Bases de données > Langage SQL
Langage SQL Forum d'entraide sur le langage SQL et sur les questions liées à la conception de schéma (DDL). Cours SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 09/05/2011, 17h52   #1
Membre régulier
 
Inscription : avril 2005
Messages : 235
Détails du profil
Informations personnelles :
Âge : 25
Localisation : France, Hérault (Languedoc Roussillon)

Informations forums :
Inscription : avril 2005
Messages : 235
Points : 78
Points : 78
Par défaut Jointure avec une seule ligne

Bonjour,

J'aimerais faire une jointure entre deux tables et n'avoir en retour qu'une seule ligne, même s'il y a plusieurs lignes correspondantes dans la seconde table, et avec une condition pour trouver laquelle retourner.

Pour bien me faire comprendre (car je suis pas sûr d'être très clair ), voici un exemple :

J'ai une table "personnes" et une table "voitures" (qui possède un champ "personne_id", clé étrangère pointant sur personnes.id).
Je voudrais retrouver toutes les personnes présentes dans la base et pour chacune avoir la voiture lui appartenant, avec la date d'achat la plus récente.

Pas sûr que ce soit faisable avec le JOIN seul. Mais sait-on jamais !

Merci d'avance.
pontus21 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/05/2011, 18h01   #2
Membre émérite
 
Homme Olivier Dehorter
Ingenieur de recherche - Ecologue
Inscription : juin 2003
Messages : 697
Détails du profil
Informations personnelles :
Nom : Homme Olivier Dehorter
Localisation : France

Informations professionnelles :
Activité : Ingenieur de recherche - Ecologue

Informations forums :
Inscription : juin 2003
Messages : 697
Points : 837
Points : 837
bonjour


non ce n'est pas tres clair

la requete de test, et un exemple de donnees en retour serait le bienvenu


et quel est le SGBD ?
dehorter olivier est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/05/2011, 18h53   #3
Membre régulier
 
Inscription : avril 2005
Messages : 235
Détails du profil
Informations personnelles :
Âge : 25
Localisation : France, Hérault (Languedoc Roussillon)

Informations forums :
Inscription : avril 2005
Messages : 235
Points : 78
Points : 78
Ok.
Alors, pas de requêtes car justement je n'ai aucune idée de comment faire.
Le SGBD est MySQL, en version 5.

Mes tables :
Personnes (id, nom, naissance)
Voitures (id, nom, date_achat, personne_id)

J'ai par exemple les données suivantes :
Personne : 1, Pontus, 01/01/1980

Voiture  : 1, C1, 02/05/2011, 1
Voiture  : 2, C2, 03/01/2010, 1
J'aimerais que ma requête me donne la personne 1 (Pontus) avec la voiture 1 (C1), soit la voiture acheté le plus récemment.
Et la même chose pour chaque personne de la table Personnes ...

Est-ce plus clair ?
Comme je ne suis pas sûr que ce que je souhaite soit possible, au pire, j'aimerais n'avoir qu'une ligne par personne, même si cette personne a acheté plusieurs voitures : quel type de jointure utiliser alors ?
pontus21 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/05/2011, 07h49   #4
Membre expérimenté
 
Inscription : octobre 2002
Messages : 654
Détails du profil
Informations forums :
Inscription : octobre 2002
Messages : 654
Points : 552
Points : 552
Bonjour,
Voilà une requete, elle est un peu compliquée parce que j'ai considéré qu'une personne pouvait acheter deux voitures le même jour, dans ce cas j'ai pris une voiture arbitrairement.
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
SELECT P.id idPersonne, p.nom NomPersonne, p.naissance, vF.id idVoiture,vF.nom nomVoiture, vf.date_achat
FROM Personnes P
INNER JOIN 
	(SELECT vm.personne_id, max(vm.date_achat) AS date_dernier_achat
		FROM Voiture vm
		GROUP BY vm.personne_id
	) V1
	ON P.id=v1.personne_id
INNER JOIN	
	(SELECT v3.personne_id, date_achat, max(V3.id) AS id_derniere_voiture_achetee
		FROM date_achat v3
		GROUP BY v3.personne_id,date_achat
	) V2
	ON v1.personne_id=V2.personne_id
	AND V1.date_dernier_achat=v2.date_achat
INNER JOIN date_achat VF
	ON VF.personne_id=V2.personne_id
	AND VF.id=id_derniere_voiture_achetee
Cela doit se simplifier énormément avec les fonctions de fenêtrage.
A+
Soazig
soazig est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/05/2011, 09h42   #5
Membre émérite
 
Avatar de Drizzt [Drone38]
 
Homme
Inscription : mai 2004
Messages : 739
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Isère (Rhône Alpes)

Informations forums :
Inscription : mai 2004
Messages : 739
Points : 979
Points : 979
Avec du fenetrage sous Oracle :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
WITH 
  personne AS (SELECT 1 id, 'P1' nom FROM dual union ALL
              SELECT 2, 'P2' FROM dual),
  voiture AS (SELECT 'C1' voiture, to_date('02/05/2011','DD/MM/YYYY') dte, 1 id_p FROM dual union ALL
              SELECT 'C2', to_date('03/01/2010','DD/MM/YYYY'), 1 FROM dual union ALL
              SELECT 'C4', to_date('02/05/2011','DD/MM/YYYY'), 1 FROM dual union ALL
              SELECT 'C2', to_date('02/05/2010','DD/MM/YYYY'), 2 FROM dual union ALL
              SELECT 'C3', to_date('02/05/2011','DD/MM/YYYY'), 2 FROM dual)
SELECT
    p.nom,
    max(v.voiture) keep(dense_rank first ORDER BY v.dte DESC) voiture
FROM personne p
LEFT JOIN voiture v ON v.id_p = p.id
GROUP BY p.nom;
Résultat:

Citation:
P1 C4
P2 C3
__________________
Je ne réponds pas aux questions techniques par MP, le forum est là pour cela.

La crypto c'est comme les flambys, une fois que tu as trouvé la languette tu as juste à tirer pour tout faire tomber.

(\ _ /)
(='.'=)
Voici Lapinou. Aidez le à conquérir le monde
(")-(") en le reproduisant
Drizzt [Drone38] est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/05/2011, 10h49   #6
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 684
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 684
Points : 10 442
Points : 10 442
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Citation:
Envoyé par Drizzt [Drone38] Voir le message
Avec du fenetrage sous Oracle
En fait ici, il n'y a pas de fenêtrage, c'est la fonction FIRST sous sa forme agrégée classique. Elle existe aussi avec son extension PARTITION BY, mais pas nécessaire dans ce cas-là.
Je me suis fait avoir aussi il y a quelques temps !
Par contre, l'auteur étant sous MySQL, je doute que ça l'aide vraiment.
__________________
Email : http://scr.im/waldar
Waldar est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/05/2011, 17h02   #7
Membre émérite
 
Avatar de Drizzt [Drone38]
 
Homme
Inscription : mai 2004
Messages : 739
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Isère (Rhône Alpes)

Informations forums :
Inscription : mai 2004
Messages : 739
Points : 979
Points : 979
C'est vrai bonne remarque. J'ai tendance à mettre un peu trop de choses sous l'appelation fenêtrage
__________________
Je ne réponds pas aux questions techniques par MP, le forum est là pour cela.

La crypto c'est comme les flambys, une fois que tu as trouvé la languette tu as juste à tirer pour tout faire tomber.

(\ _ /)
(='.'=)
Voici Lapinou. Aidez le à conquérir le monde
(")-(") en le reproduisant
Drizzt [Drone38] est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/05/2011, 10h44   #8
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 11 000
Détails du profil
Informations personnelles :
Nom : Homme Philippe Leménager
Âge : 48
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations professionnelles :
Activité : Ingénieur d'études en informatique
Secteur : Enseignement

Informations forums :
Inscription : août 2006
Messages : 11 000
Points : 18 265
Points : 18 265
Envoyer un message via MSN à CinePhil
Quelle est, pour chaque personne, la dernière voiture qu'il a achetée ?
Code :
1
2
3
4
SELECT p.id, MAX(v.date_achat) AS dernier_achat
FROM Personne p
LEFT OUTER JOIN Voiture v ON v.personne_id = p.id
GROUP BY p.id
Quelle est la voiture correspondant à cette date d'achat pour chaque personne ?
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT tmp.nom AS nom_personne, 
    v1.nom AS nom_voiture,
    v1.date_achat
FROM Voiture v1
INNER JOIN 
(
    SELECT p.id, p.nom, MAX(v.date_achat) AS dernier_achat
    FROM Personne p
    LEFT OUTER JOIN Voiture v ON v.personne_id = p.id
    GROUP BY p.id, p.nom
) tmp 
    ON tmp.id = v1.personne_id
    AND tmp.dernier_achat = v1.date_achat
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique.
Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework...
« Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
À la maison comme au bureau, j'utilise Mandriva Linux ou Mageïa ! Soutenons l'industrie logicielle française !
Linuxiens, comptez-vous !
CinePhil est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 11h05.


 
 
 
 
Partenaires

Hébergement Web