IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage SQL Discussion :

[SQL] Colonne unique


Sujet :

Langage SQL

  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2007
    Messages
    634
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2007
    Messages : 634
    Points : 407
    Points
    407
    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

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 388
    Points
    18 388
    Par défaut
    Quelle est la règle de sélection ?

  3. #3
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2007
    Messages
    634
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2007
    Messages : 634
    Points : 407
    Points
    407
    Par défaut
    La requête que j'utilise actuellement, ressemble a cela : (j'ai renomme les champs et tables) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  4. #4
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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 : 16 801
    Points : 34 063
    Points
    34 063
    Billets dans le blog
    14
    Par défaut
    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 ?

  5. #5
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2007
    Messages
    634
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2007
    Messages : 634
    Points : 407
    Points
    407
    Par défaut
    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

  6. #6
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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 : 16 801
    Points : 34 063
    Points
    34 063
    Billets dans le blog
    14
    Par défaut
    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 !

  7. #7
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 388
    Points
    18 388
    Par défaut
    Et aussi, quelle version de SQL-Server ?

  8. #8
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2007
    Messages
    634
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2007
    Messages : 634
    Points : 407
    Points
    407
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  9. #9
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 388
    Points
    18 388
    Par défaut
    Ok c'est maintenant parfaitement clair.
    Essayez ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  10. #10
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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 : 16 801
    Points : 34 063
    Points
    34 063
    Billets dans le blog
    14
    Par défaut
    Que d'erreurs dans cette requête !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 !

    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  11. #11
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    bonjour,

    ou cela :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    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'

  12. #12
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2007
    Messages
    634
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2007
    Messages : 634
    Points : 407
    Points
    407
    Par défaut
    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.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [T-SQL] Colonnes d'une table appelées avec une variable
    Par Deedoo2000 dans le forum Adaptive Server Enterprise
    Réponses: 3
    Dernier message: 25/09/2006, 15h18
  2. [Sql] colonnes d'une table
    Par atanabe dans le forum Oracle
    Réponses: 3
    Dernier message: 03/08/2006, 09h08
  3. importer des fichiers mp3 avec sql server uniquement
    Par cool dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 08/04/2006, 13h21
  4. [SQL]Retour d'une colonne unique
    Par Le nain Attila dans le forum Oracle
    Réponses: 4
    Dernier message: 31/03/2006, 16h26
  5. Distinct sur colonne unique
    Par Dnx dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 14/11/2005, 10h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo