Précédent   Forum des professionnels en informatique > Bases de données > MS SQL-Server > Développement
Développement Forum d'entraide sur le Transact-SQL, le CLR, les procédures stockées, les triggers, les requêtes 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 24/11/2010, 17h55   #1
Membre chevronné
 
Avatar de Hervé Saladin
 
Développeur Web
Inscription : décembre 2004
Messages : 636
Détails du profil
Informations personnelles :
Âge : 30

Informations professionnelles :
Activité : Développeur Web

Informations forums :
Inscription : décembre 2004
Messages : 636
Points : 689
Points : 689
Par défaut Limiter le nombre de correspondance dans une jointure externe ?

Bonjour,
ce que j'ai besoin de faire est un peu tordu, je vous passe les détails du pourquoi, c'est comme ça et il faut absolument que j'y arrive, et il faut que j'y arrive en SQL uniquement (pas le droit de traiter les résultats après dans le programme client).

Disons que j'ai deux tables A et B, avec une clé étrangère de B vers A, plusieurs enregistrements de B peuvent correspondre à un enregistrement de A (0, n) :
Code :
1
2
A (ida, champa1, champa2, champa3)
B (ida#, champb1)
Je voudrais sélectionner tous les champs de A (tous les enregistrements), en y ajoutant la première occurence de B trouvée (NULL si aucune correspondance)
Au final, je dois avoir un résultat ayant les champs :
Code :
ida, champa1, champa2, champa3, champb1
Et ce résultat doit retourner EXACTEMENT le même nombre de ligne que dans la table A.
Il ne faut pas exclure les enregistrements de A n'ayant pas de correspondance dans B (donc j'imagine que c'est une jointure externe ?), et il ne faut avoir que la 1ere occurrence (dans l'ordre de la sélection) de champb1, tant pis s'il y a d'autres correspondances, elles doivent passer à la trappe (et ça je n'ai pas encore trouvé comment faire).

Oui, je sais, c'est tordu ...

Pour l'instant je fais ceci comme requête :
Code :
1
2
3
SELECT A.ida, A.champa1, A.champa2, Achampa3, B.champb1
FROM A
LEFT OUTER JOIN B ON A.ida = B.ida
C'est presque bon, sauf que si un enregistrement de A à plusieurs correspondances dans B, j'obtiensw plusieurs lignes dans le résultat (normal).
Ce qu'il me faudrait (si ça existait), ça serait quelque chose du genre :
Code :
1
2
3
SELECT A.ida, A.champa1, A.champa2, Achampa3, B.champb1
FROM A
LEFT OUTER JOIN B ON A.ida = B.ida LIMIT 1
Comment obtenir quelque chose d'équivalent sans traiter le résultat a posteriori ?

Merci beaucoup à celui ou celle qui pourra me sauver sur ce coup-là !

(PS : c'est sous SQL Server 2005)
__________________
Ne cliquez pas sur ce lien
Hervé Saladin est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/11/2010, 19h15   #2
Modérateur

 
Avatar de elsuket
 
Homme Nicolas Souquet
Administrateur de base de données
Inscription : janvier 2005
Messages : 4 660
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Souquet
Âge : 30
Localisation : Thaïlande

Informations professionnelles :
Activité : Administrateur de base de données
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : janvier 2005
Messages : 4 660
Points : 8 690
Points : 8 690
Bonjour,

Citation:
Il ne faut pas exclure les enregistrements de A n'ayant pas de correspondance dans B (donc j'imagine que c'est une jointure externe ?)
C'est exact et votre code plus bas correspond à cette affirmation.

Citation:
et il ne faut avoir que la 1ere occurrence (dans l'ordre de la sélection) de champb1
Comment déterminez-vous cet ordre ? Il n'y a pas de clause ORDER BY dans votre requête

LIMIT n'est pas SQL car il n'est pas ensembliste

@++
__________________
En bases de données relationnelles SQL, il n'y a ni tableaux, ni enregistrements, ni champs: il y a des tables, des lignes et des colonnes.
Blog | Profil| Consulter ou télécharger les fichiers d'aide de SQL Server, des versions 2000 à 2012
elsuket est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/11/2010, 19h41   #3
Membre chevronné
 
Avatar de Hervé Saladin
 
Développeur Web
Inscription : décembre 2004
Messages : 636
Détails du profil
Informations personnelles :
Âge : 30

Informations professionnelles :
Activité : Développeur Web

Informations forums :
Inscription : décembre 2004
Messages : 636
Points : 689
Points : 689
Citation:
Comment déterminez-vous cet ordre ? Il n'y a pas de clause ORDER BY dans votre requête
Aucune importance, la première ligne venue fera l'affaire ... oui, je sais, c'est bizzare, mais faut pas chercher à comprendre : c'est comme ça (il y a bien une justificattion découlant du type de données que j'extrait et de la nature de la demande à la quelle je dois répondre mais je ne vais pas m'étendre dessus, ni sur son bien-fondé).

Citation:
LIMIT n'est pas SQL car il n'est pas ensembliste
Oui, je sais que ce n'est pas valable (sinon j'aurais la solution et je n'aurais pas besoin d'aide), c'était juste pour illustrer ce que j'ai besoin de faire.

Comment arriver au même résultat par un autre moyen ?
__________________
Ne cliquez pas sur ce lien
Hervé Saladin est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/11/2010, 03h08   #4
Modérateur

 
Avatar de elsuket
 
Homme Nicolas Souquet
Administrateur de base de données
Inscription : janvier 2005
Messages : 4 660
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Souquet
Âge : 30
Localisation : Thaïlande

Informations professionnelles :
Activité : Administrateur de base de données
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : janvier 2005
Messages : 4 660
Points : 8 690
Points : 8 690
Vous pouvez par exemple utiliser la fonction de fenêtrage ROW_NUMBER() :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
;WITH
	CTE AS
	(
		SELECT		A.ida
				, A.champa1
				, A.champa2
				, A.champa3
				, B.champb1
				, ROW_NUMBER() OVER(PARTITION BY A.ida ORDER BY B.champb1) AS n
		FROM		dbo.A AS A
		LEFT JOIN	dbo.B AS B ON A.ida = B.ida
	)
SELECT	ida
	, champa1
	, champa2
	, champa3
	, champb1
FROM	CTE
WHERE	n = 1
@++
__________________
En bases de données relationnelles SQL, il n'y a ni tableaux, ni enregistrements, ni champs: il y a des tables, des lignes et des colonnes.
Blog | Profil| Consulter ou télécharger les fichiers d'aide de SQL Server, des versions 2000 à 2012
elsuket est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/11/2010, 11h23   #5
Membre chevronné
 
Avatar de Hervé Saladin
 
Développeur Web
Inscription : décembre 2004
Messages : 636
Détails du profil
Informations personnelles :
Âge : 30

Informations professionnelles :
Activité : Développeur Web

Informations forums :
Inscription : décembre 2004
Messages : 636
Points : 689
Points : 689
Super, ça marche au poil !

Merci mille fois !!! Je pense que je n'aurais pas trouvé tout seul, ou alors j'aurais galéré pendant des lustres.

Comme dirait l'autre : ça m'enlève une fière chandelle du pied

Encore merci !
__________________
Ne cliquez pas sur ce lien
Hervé Saladin est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/11/2010, 11h27   #6
Modérateur

 
Avatar de elsuket
 
Homme Nicolas Souquet
Administrateur de base de données
Inscription : janvier 2005
Messages : 4 660
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Souquet
Âge : 30
Localisation : Thaïlande

Informations professionnelles :
Activité : Administrateur de base de données
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : janvier 2005
Messages : 4 660
Points : 8 690
Points : 8 690
Avec plaisir
__________________
En bases de données relationnelles SQL, il n'y a ni tableaux, ni enregistrements, ni champs: il y a des tables, des lignes et des colonnes.
Blog | Profil| Consulter ou télécharger les fichiers d'aide de SQL Server, des versions 2000 à 2012
elsuket est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 16h58.


 
 
 
 
Partenaires

Hébergement Web