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/06/2011, 16h03   #1
Membre éclairé
 
Homme
Étudiant
Inscription : novembre 2007
Messages : 594
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 24
Localisation : France, Loire (Rhône Alpes)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : novembre 2007
Messages : 594
Points : 344
Points : 344
Par défaut [SQL] Colonne unique

Bonjour a tous,

J'ai un soucis concernant une requête SQL sous SQL Server.

J'ai une requête me retournant un resultat qui ressemble a ceci


1 | X1 | X | X .....
2 | X2 | X | X .....
1 | X | X | X .....
2 | X | X | X .....
3 | X3 | X | X .....
2 | X | X | X .....
1 | X | X | X .....
2 | X | X | X .....

et je voudrais obtenir ceci :

1 | X1 | X | X .....
2 | X2 | X | X .....
3 | X3 | X | X .....

J'avoue que je bloque totalement, j'ai essaye avec DISTINCT le problème est que ça prend toutes les colonne et pas seulement la première. Group by sans succès...

Si vous avez une idée, n’hésitez pas !

Merci d'avance.

NeoKript
NeoKript est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/06/2011, 16h05   #2
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 434
Points : 10 434
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Quelle est la règle de sélection ?
__________________
Email : http://scr.im/waldar
Waldar est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/06/2011, 16h14   #3
Membre éclairé
 
Homme
Étudiant
Inscription : novembre 2007
Messages : 594
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 24
Localisation : France, Loire (Rhône Alpes)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : novembre 2007
Messages : 594
Points : 344
Points : 344
La requête que j'utilise actuellement, ressemble a cela : (j'ai renomme les champs et tables) :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
SELECT
		[X].[A],
		[X].[Id],
		[Z].[Name],
		[Y].[B],
		[Y].[ModificationDatetime],
		[X].[C]
	FROM
		[dbo].[X],
		[dbo].[Z],
		[dbo].[Y]
	WHERE
			[X].[A] = @Id
		AND 
			[Y].[ProdId] = [X].[Id]
		AND
			[X].[ParentId] = NULL
		AND 
			[Z].[Id] IN 
			(
				SELECT 
					[U].[ProcId]
				FROM
					[dbo].[U]
				WHERE
					[U].[Id] = [X].[ProdId]
			)
	ORDER BY [Y].[Datetime] DESC

En gros, c'est un join entre 3 table et j'aimerai que la colonne [X].[Id] soit unique.

Merci encore
NeoKript est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/06/2011, 16h23   #4
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 11 003
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 003
Points : 18 265
Points : 18 265
Envoyer un message via MSN à CinePhil
Pour commencer, selon la norme SQL et depuis 1992, les jointures s'écrivent avec JOIN. Près de 20 ans plus tard, il serait temps de s'y mettre !

Par définition, ID est unique dans la table X1 non ?
C'est la jointure avec les autres tables qui produit potentiellement plusieurs lignes pour chaque valeur de X1.ID ?

Je pose alors la même question que Waldar : Comment choisir parmi ces multiples lignes pour une valeur de X1.ID quelle ligne doit être conservée ?
__________________
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 actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/06/2011, 16h32   #5
Membre éclairé
 
Homme
Étudiant
Inscription : novembre 2007
Messages : 594
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 24
Localisation : France, Loire (Rhône Alpes)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : novembre 2007
Messages : 594
Points : 344
Points : 344
Citation:
Envoyé par CinePhil Voir le message
Pour commencer, selon la norme SQL et depuis 1992, les jointures s'écrivent avec JOIN. Près de 20 ans plus tard, il serait temps de s'y mettre !
Ce n'est pas moi qui vais dire le contraire mais la ou je fais mon stage, il n'aime pas les JOIN

Citation:
Envoyé par CinePhil Voir le message
Par définition, ID est unique dans la table X1 non ?
Id est bien unique (Cle primaire auto incrémente)

Citation:
Envoyé par CinePhil Voir le message
C'est la jointure avec les autres tables qui produit potentiellement plusieurs lignes pour chaque valeur de X1.ID ?
Exact !

Citation:
Envoyé par CinePhil Voir le message
Je pose alors la même question que Waldar : Comment choisir parmi ces multiples lignes pour une valeur de X1.ID quelle ligne doit être conservée ?
Je ne comprend pas trop la question.

Id | C2 | C3 | C4..... (C2 = Colonne 2... X = Valeur sans importance)
---------------------
1 | X1 | X | X .....
2 | X2 | X | X .....
1 | X | X | X .....
2 | X | X | X .....
3 | X3 | X | X .....
2 | X | X | X .....
1 | X | X | X .....
2 | X | X | X .....

Je voudrait que le résultat précédent devienne
Id | C2 | C3 | C4.....
---------------------
1 | X1 | X | X .....
2 | X2 | X | X .....
3 | X3 | X | X .....

Les lignes du premier tableau sont trier par Date (Voir ORDER BY de la requête) et j'aimerai prendre toutes les premières valeurs afin de ne pas avoir de Id duplique..

Si ce n'est pas claire dite moi, j’essaierai de mieux expliquer.

Merci encore.

NeoKript
NeoKript est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/06/2011, 16h42   #6
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 11 003
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 003
Points : 18 265
Points : 18 265
Envoyer un message via MSN à CinePhil
Voilà ce que c'est de vouloir faire des abstractions trop fortes par rapport aux données réelles !

Dans ta requête, tu manipules les colonnes X.A, X.ID, Z.Name, Y.B, Y.ModificationDateTime, et X.C et dans ton dernier exemple de données tu présentes Id, C2, C3, C4. Comment veux-tu qu'on s'y retrouve ?

Alors lis les règles du forum et applique-les, si besoin en changeant les noms et autres informations confidentielles mais avec un jeu de données qui ressemble au réel et un résultat attendu correspondant au jeu de données fourni !
__________________
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 actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/06/2011, 16h45   #7
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 434
Points : 10 434
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Et aussi, quelle version de SQL-Server ?
__________________
Email : http://scr.im/waldar
Waldar est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/06/2011, 17h01   #8
Membre éclairé
 
Homme
Étudiant
Inscription : novembre 2007
Messages : 594
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 24
Localisation : France, Loire (Rhône Alpes)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : novembre 2007
Messages : 594
Points : 344
Points : 344
La BDD utilisée est SQL Server 2005

Alors voila la requête, j'ai juste changer le nom des tables en Table 1, Table 2, histoire que ce soit plus clair.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SELECT [Table1].[ProductionRequestId],
       [Table1].[Id],
       [Table2].[Name],
       [Table3].[StateId],
       [Table3].[ModificationDatetime],
       [Table1].[ProductSegmentId]
FROM   [dbo].[Table1],
       [dbo].[Table2],
       [dbo].[Table3]
WHERE  [Table1].[ProductionRequestId] = @ProductionRequestId
       AND [Table3].[Table1Id] = [Table1].[Id]
       AND [Table1].[ParentId] = NULL
       AND [Table2].[Id] IN (SELECT [Table4].[Id]
                             FROM   [dbo].[Table4]
                             WHERE  [Table4].[Id] = [Table1].[ProductSegmentId])
ORDER  BY [Table3].[ModificationDatetime] DESC

Résultat :
Code :
1
2
3
4
5
6
 
[ProductionRequestId] [Id] [Name] [StateId] [ModificationDateTime] [ProductSegmentId]
57	313	Conditionnement	READY	2011-06-09 15:17:37.337	68
57	308	Preparation	READY	2011-06-09 15:17:37.333	63
57	313	Conditionnement	OPENED	2011-06-09 15:17:34.040	68
57	308	Preparation	OPENED	2011-06-09 15:17:34.033	63
En gros, il y a une table de jointure contenant l'historique des changements d’états, et je voudrais seulement récupéré le dernier état (READY).

Code :
1
2
3
4
 
[ProductionRequestId] [Id] [Name] [StateId] [ModificationDateTime] [ProductSegmentId]
57	313	Conditionnement	READY	2011-06-09 15:17:37.337	68
57	308	Preparation	READY	2011-06-09 15:17:37.333	63
Merci encore
NeoKript est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/06/2011, 17h16   #9
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 434
Points : 10 434
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Ok c'est maintenant parfaitement clair.
Essayez ainsi :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
WITH SR AS
(
SELECT [Table1].[ProductionRequestId],
       [Table1].[Id],
       [Table2].[Name],
       [Table3].[StateId],
       [Table3].[ModificationDatetime],
       [Table1].[ProductSegmentId],
       ROW_NUMBER() OVER(PARTITION BY [Table1].[Id] ORDER BY [Table3].[ModificationDatetime] DESC) AS RN
FROM   [dbo].[Table1],
       [dbo].[Table2],
       [dbo].[Table3]
WHERE  [Table1].[ProductionRequestId] = @ProductionRequestId
       AND [Table3].[Table1Id] = [Table1].[Id]
       AND [Table1].[ParentId] = NULL
       AND [Table2].[Id] IN (SELECT [Table4].[Id]
                             FROM   [dbo].[Table4]
                             WHERE  [Table4].[Id] = [Table1].[ProductSegmentId])
)
SELECT *
  FROM SR
 WHERE RN = 1
__________________
Email : http://scr.im/waldar
Waldar est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/06/2011, 17h34   #10
Modérateur
 
Avatar de CinePhil
 
Homme Philippe Leménager
Ingénieur d'études en informatique
Inscription : août 2006
Messages : 11 003
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 003
Points : 18 265
Points : 18 265
Envoyer un message via MSN à CinePhil
Que d'erreurs dans cette requête !

Code :
AND [Table1].[ParentId] = NULL
FAUX ! C'est IS NULL !
Le seul cas où on doit écrire = NULL est dans une requête UPDATE pour mettre à NULL une colonne.

En essayant de normaliser l'écriture de ta requête, je constate qu'il manque une condition de jointure pour Table2 ! Tu t'en serais aperçu en écrivant correctement la requête !
Mais en réalité, si j'interprète correctement la requête, ce qui demeure difficile avec l'abstraction du nom des tables et le manque d'information sur leur structure et ce qu'elles contiennent, il me semble que la dernière restriction du WHERE est en fait une jointure de Table1 avec Table4 puis une jointure de Table4 avec Table2, ce qui devrait être plus performant qu'une sous-requête corrélée.

[Beurk !] [on] [dirait] [de] [l'access !]
Dans la phrase ci-dessus, seuls les premiers et derniers crochets sont nécessaires car ce ne sont pas des noms conformes et dans ta requête aucun ne l'est ! Ça facilite l'écriture et la lecture de la requête.

L'utilisation d'alias courts faciliterait aussi l'écriture et la lecture de la requête !

Citation:
je voudrais seulement récupéré le dernier état (READY).
Pourquoi ne pas tout simplement mettre une restriction sur cet état ?
Et au passage, ID textuel, c'est pas top !

La requête deviendrait celle-ci :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT t1.ProductionRequestId,
    t1.Id,
    t2.Name,
    t3.StateId,
    t3.ModificationDateTime,
    t1.ProductSegmentId
FROM dbo.Table1 t1
INNER JOIN dbo.Table4 t4 ON t4.Id = t1.ProductSegmentId
    INNER JOIN dbo.Table2 t2 ON t2.Id = t4.Id
INNER JOIN dbo.Table3 t3 ON t3.Table1Id = t1.Id
WHERE t1.ProductionRequestId = @ProductionRequestId
    AND t1.ParentId IS NULL
    AND t3.StateId = 'READY'
ORDER BY t3.ModificationDateTime
__________________
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 actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/06/2011, 17h39   #11
Membre Expert
 
Inscription : janvier 2010
Messages : 1 084
Détails du profil
Informations personnelles :
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : janvier 2010
Messages : 1 084
Points : 1 573
Points : 1 573
bonjour,

ou cela :

Code SQL :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
SELECT T1.[ProductionRequestId],
       T1.[Id],
       T2.[Name],
       T3.[StateId],
       T3.[ModificationDatetime],
       T1.[ProductSegmentId]
FROM   [dbo].[Table1] T1
INNER JOIN [dbo].[Table4] T4
	ON T4.id = T1.[ProductSegmentId]
INNER JOIN  [dbo].[Table2] T2
	ON T2.Id = T4.Id
CROSS APPLY (
	SELECT TOP(1) [StateId], [ModificationDatetime]
	FROM [Table3] X
	WHERE X.TableId = T1.Id
	ORDER BY [ModificationDatetime] DESC
) T3
WHERE T1.parentID IS NULL
ORDER  BY T3.[ModificationDatetime] DESC

Avec éventuellement (selon votre besoin) un filtre (dans le cross apply) pour ne récupérer que les ligne dans l'etat 'READY'
aieeeuuuuu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/06/2011, 08h29   #12
Membre éclairé
 
Homme
Étudiant
Inscription : novembre 2007
Messages : 594
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 24
Localisation : France, Loire (Rhône Alpes)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : novembre 2007
Messages : 594
Points : 344
Points : 344
Salut !

Merci pour vos réponses, la requête de Waldar fonctionne parfaitement, je vais essayer celle de aieeeuuuuu. Je ne connaissais pas la clause WITH ni la clause CROSS APPLY.

Pour les Id textuels, ce n'est pas moi qui ai créé les tables sinon ça serait AI de partout.

Et pour le IS NULL, j'en prends note !

Merci pour tout.
NeoKript 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 15h58.


 
 
 
 
Partenaires

Hébergement Web