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

MS SQL Server Discussion :

Concatenation du resultat d'un SELECT sur une colonne sans la première et dernière ligne


Sujet :

MS SQL Server

  1. #1
    Membre du Club
    Inscrit en
    Janvier 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 107
    Points : 43
    Points
    43
    Par défaut Concatenation du resultat d'un SELECT sur une colonne sans la première et dernière ligne
    Salut,


    je vous donne une idée sur ce que je veux faire :

    exemple : select VAL from TABLE

    resultat :

    1
    2
    ...
    5

    je dois récupérer une chaine de caractères de cette manière :

    chaine résultat : 2, 3 et 4

    Y'a t-il un moyen pour qu'une requête SELECT sur une colonne retourne touts les lignes sauf la première et la dernière ?
    Merci d'avance

  2. #2
    Expert éminent sénior
    Avatar de mikedavem
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2005
    Messages
    5 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Distribution

    Informations forums :
    Inscription : Août 2005
    Messages : 5 450
    Points : 12 891
    Points
    12 891
    Par défaut
    Bonjour,

    Quel est vote but ?

    ++

  3. #3
    Membre du Club
    Inscrit en
    Janvier 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 107
    Points : 43
    Points
    43
    Par défaut
    Citation Envoyé par mikedavem Voir le message
    Bonjour,

    Quel est vote but ?

    ++
    Bonjour, je voudrais récupérer dans un jeu de résultats d'un SELECT toutes les lignes sauf la première et la dernière

    Merci

  4. #4
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

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

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Bonjour,

    Il n'y a pas d'ordre en SQL.
    Donc vous êtes obligé de le générer, ce qui peut être coûteux :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    ;WITH
    	CTE_ORDER AS
    	(
    		SELECT	val
    			, ROW_NUMBER() OVER(ORDER BY val) AS n
    		FROM	dbo.maTable
    	)
    SELECT		O.val
    FROM		CTE_ORDER AS O
    CROSS APPLY	(
    			SELECT	MAX(n) - 1 AS max_n 
    			FROM	CTE_ORDER
    		) AS M
    WHERE		O.n BETWEEN 2 AND M.max_n
    @++

  5. #5
    Membre du Club
    Inscrit en
    Janvier 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 107
    Points : 43
    Points
    43
    Par défaut
    Citation Envoyé par elsuket Voir le message
    Bonjour,

    Il n'y a pas d'ordre en SQL.
    Donc vous êtes obligé de le générer, ce qui peut être coûteux :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    ;WITH
    	CTE_ORDER AS
    	(
    		SELECT	val
    			, ROW_NUMBER() OVER(ORDER BY val) AS n
    		FROM	dbo.maTable
    	)
    SELECT		O.val
    FROM		CTE_ORDER AS O
    CROSS APPLY	(
    			SELECT	MAX(n) - 1 AS max_n 
    			FROM	CTE_ORDER
    		) AS M
    WHERE		O.n BETWEEN 2 AND M.max_n
    @++
    Merci infiniment,
    Peux tu m'expliquer ce bout de code STP ?

  6. #6
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 847
    Points : 52 955
    Points
    52 955
    Billets dans le blog
    6
    Par défaut
    C'est une requête SQL... Il vous suffit d'apprendre le SQL. Mon site web, comme mon livre peuvent vous y aider !

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  7. #7
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

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

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Même si SQLPro a totalement raison, (je vous invite d'ailleurs fortement à parcourir son site !), voici les détails :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ;WITH
    	CTE_ORDER AS
    	(
    		SELECT	val
    			, ROW_NUMBER() OVER(ORDER BY val) AS n
    		FROM	dbo.maTable
    	)
    C'est une expression de table commune (Common Table Expression / CTE dans la littérature Anglaise) : il s'agit d'une vue qui n'a d'existence que pour la durée de la transaction.
    Ici on lui fait ordonner les valeurs de la colonne val, en affectant un numéro de ligne (ROW_NUMBER()) suivant cet ordre (clause OVER()).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    CROSS APPLY	(
    			SELECT	MAX(n) - 1 AS max_n 
    			FROM	CTE_ORDER
    		) AS M
    Nous avons besoin de connaître le nombre de lignes que comprend la CTE.
    Donc on recherche le MAX(n), et on l'applique (APPLY) à l'ensemble des lignes retournées par la CTE.
    En fait d'utilisation de APPLY, on force SQL Server à n'effectuer qu'une seule fois ce calcul, plutôt que de l'effectuer pour chaque ligne.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WHERE		O.n BETWEEN 2 AND M.max_n
    Ici on prend les indices de lignes numéro 2 et MAX(n) - 1 : l'avant dernier.
    Cela nous filtrera donc les valeurs de la colonne val comme vous le souhaitiez.

    @++

  8. #8
    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

    si vous voulez le résultat sous forme de chaine de caractères, vous pouvez aussi faire comme ça :

    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    /* jeu d'essai */
    DECLARE @T TABLE(val varchar(8000))
     
    ;WITH T (n) AS (
    	SELECT 'a'
    	UNION ALL
    	SELECT 'b'
    	UNION ALL
    	SELECT 'c'
    	UNION ALL
    	SELECT 'd'
    )
    INSERT INTO @T
    SELECT *
    FROM T
     
    /* /jeu essai */
     
     
    DECLARE @Res VARCHAR(8000)
    DECLARE @Tmp VARCHAR(8000)
     
    SELECT 
    	@Res = 
    		CASE 
    			WHEN @Tmp IS NULL 
    				THEN NULL 
    			ELSE 
    				CASE 
    					WHEN @Res IS NULL 
    						THEN ''
    					ELSE 
    						@Res 
    						+ CASE WHEN @Res <> '' THEN ',' ELSE '' END
    						+ @Tmp
    				END
    		END,
    	@Tmp = val
    FROM @T T
    ORDER BY val --mettre ici l'ordre voulu
     
    SELECT @Res

    Avec un petite bidouille supplémentaire, vous pouvez aussi remplacer la dernière virgule par un "et"...

    par contre, quant à la question de mikedavem :
    Quel est vote but ?
    je pense que le fond de la question était plutôt :
    Que voulez vous faire de cette chaine par la suite ?

    Ce type d'opération aurait plus sa place dans le code client...

  9. #9
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

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

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Ho j'avais pas vu

    Une autre possibilité :

    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
    DECLARE @sql varchar(max)
     
    ;WITH
    	CTE_ORDER AS
    	(
    		SELECT	val
    			, ROW_NUMBER() OVER(ORDER BY val) AS n
    		FROM	dbo.maTable
    	)
    SELECT		@sql = CASE
    				WHEN @sql IS NULL THEN CAST(O.val AS varchar(10))
    				ELSE @sql + ', ' + CAST(O.val AS varchar(10))
    			END
    FROM		CTE_ORDER AS O
    CROSS APPLY	(
    			SELECT	MAX(n) - 1 AS max_n 
    			FROM	CTE_ORDER
    		) AS M
    WHERE		O.n BETWEEN 2 AND M.max_n
     
    SELECT	@sql
    @++

  10. #10
    Membre du Club
    Inscrit en
    Janvier 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 107
    Points : 43
    Points
    43
    Par défaut
    Citation Envoyé par elsuket Voir le message
    Même si SQLPro a totalement raison, (je vous invite d'ailleurs fortement à parcourir son site !), voici les détails :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ;WITH
    	CTE_ORDER AS
    	(
    		SELECT	val
    			, ROW_NUMBER() OVER(ORDER BY val) AS n
    		FROM	dbo.maTable
    	)
    C'est une expression de table commune (Common Table Expression / CTE dans la littérature Anglaise) : il s'agit d'une vue qui n'a d'existence que pour la durée de la transaction.
    Ici on lui fait ordonner les valeurs de la colonne val, en affectant un numéro de ligne (ROW_NUMBER()) suivant cet ordre (clause OVER()).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    CROSS APPLY	(
    			SELECT	MAX(n) - 1 AS max_n 
    			FROM	CTE_ORDER
    		) AS M
    Nous avons besoin de connaître le nombre de lignes que comprend la CTE.
    Donc on recherche le MAX(n), et on l'applique (APPLY) à l'ensemble des lignes retournées par la CTE.
    En fait d'utilisation de APPLY, on force SQL Server à n'effectuer qu'une seule fois ce calcul, plutôt que de l'effectuer pour chaque ligne.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WHERE		O.n BETWEEN 2 AND M.max_n
    Ici on prend les indices de lignes numéro 2 et MAX(n) - 1 : l'avant dernier.
    Cela nous filtrera donc les valeurs de la colonne val comme vous le souhaitiez.

    @++
    Un grand Merci ^^
    j'ai voulu avoir des explications parce que j'aime pas faire du copier coller, il faut comprendre les choses quand meme...

  11. #11
    Membre du Club
    Inscrit en
    Janvier 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 107
    Points : 43
    Points
    43
    Par défaut
    Citation Envoyé par SQLpro Voir le message
    C'est une requête SQL... Il vous suffit d'apprendre le SQL. Mon site web, comme mon livre peuvent vous y aider !

    A +
    Merci,
    j'ai rien trouvé dans SQL pour extraire toutes les lignes sauf la premiere et la derniere

  12. #12
    Membre du Club
    Inscrit en
    Janvier 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 107
    Points : 43
    Points
    43
    Par défaut
    Merci tout le monde, je vais consulter le site c'est promis ^^

    Merci encore.

  13. #13
    Membre du Club
    Inscrit en
    Janvier 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 107
    Points : 43
    Points
    43
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    Bonjour

    si vous voulez le résultat sous forme de chaine de caractères, vous pouvez aussi faire comme ça :

    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    /* jeu d'essai */
    DECLARE @T TABLE(val varchar(8000))
     
    ;WITH T (n) AS (
    	SELECT 'a'
    	UNION ALL
    	SELECT 'b'
    	UNION ALL
    	SELECT 'c'
    	UNION ALL
    	SELECT 'd'
    )
    INSERT INTO @T
    SELECT *
    FROM T
     
    /* /jeu essai */
     
     
    DECLARE @Res VARCHAR(8000)
    DECLARE @Tmp VARCHAR(8000)
     
    SELECT 
    	@Res = 
    		CASE 
    			WHEN @Tmp IS NULL 
    				THEN NULL 
    			ELSE 
    				CASE 
    					WHEN @Res IS NULL 
    						THEN ''
    					ELSE 
    						@Res 
    						+ CASE WHEN @Res <> '' THEN ',' ELSE '' END
    						+ @Tmp
    				END
    		END,
    	@Tmp = val
    FROM @T T
    ORDER BY val --mettre ici l'ordre voulu
     
    SELECT @Res

    Avec un petite bidouille supplémentaire, vous pouvez aussi remplacer la dernière virgule par un "et"...

    par contre, quant à la question de mikedavem :


    je pense que le fond de la question était plutôt :
    Que voulez vous faire de cette chaine par la suite ?

    Ce type d'opération aurait plus sa place dans le code client...

    l'objectif principal c'est d'avoir à partir d'un ID l'ensemble des villes qu'un autocar doit visiter sans mettre les villes de depart et d'arrivé... ( vu la conception de la BD les villes de depart et d'arrivé sont stockés dans d'autres tables a part la table contenant les villes à visiter...
    et le resultat c pour l'imprimer avec Crystal reaport
    j'ai simplifier dans le but de faciliter la comprehesion

  14. #14
    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
    Citation Envoyé par LePassager Voir le message
    j'ai simplifier dans le but de faciliter la compréhension
    Vous avez surtout compliqué le problème

    Si vos villes de départ et d'arrivée sont clairement identifiées... alors il suffit de les retirer du résultat avec un filtre, ce qui a plus de sens pour SQL que de retirer "la première et la dernière ligne".

  15. #15
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

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

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    En fait c'est votre modèle qui est faux : il suffit pour cela d'ajouter une colonne avec la liste des points / arrêts du parcours, et leur indice dans le parcours.

    Comme ce genre de table change peu, vous pouvez ensuite créer une vue indexée qui vous donne pour chaque parcours le MIN() et le MAX() de l'indice.

    La requête est alors enfantine ...

    @++

  16. #16
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 847
    Points : 52 955
    Points
    52 955
    Billets dans le blog
    6
    Par défaut
    Si vous cherchez à parcourir des chemins à partir d'une table de distance, il vous faut une requête récursive.
    D'autant plus si vous voulez retrouver le plus court chemin !
    Lisez l'article que j'ai écrit à ce sujet : http://sqlpro.developpez.com/cours/s...ursives/#LIV-B

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  17. #17
    Membre du Club
    Inscrit en
    Janvier 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 107
    Points : 43
    Points
    43
    Par défaut
    Citation Envoyé par elsuket Voir le message
    En fait c'est votre modèle qui est faux : il suffit pour cela d'ajouter une colonne avec la liste des points / arrêts du parcours, et leur indice dans le parcours.

    Comme ce genre de table change peu, vous pouvez ensuite créer une vue indexée qui vous donne pour chaque parcours le MIN() et le MAX() de l'indice.

    La requête est alors enfantine ...

    @++
    Merci encore, je suis encore debutant SQL ^^

  18. #18
    Membre du Club
    Inscrit en
    Janvier 2009
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 107
    Points : 43
    Points
    43
    Par défaut
    Citation Envoyé par SQLpro Voir le message
    Si vous cherchez à parcourir des chemins à partir d'une table de distance, il vous faut une requête récursive.
    D'autant plus si vous voulez retrouver le plus court chemin !
    Lisez l'article que j'ai écrit à ce sujet : http://sqlpro.developpez.com/cours/s...ursives/#LIV-B

    A +
    Interessant comme idée, Merci

Discussions similaires

  1. Réponses: 16
    Dernier message: 24/05/2013, 12h38
  2. Réponses: 4
    Dernier message: 13/11/2009, 15h48
  3. AVG + SELECT sur une colonne ?
    Par brolon dans le forum SQL
    Réponses: 6
    Dernier message: 05/02/2009, 08h05
  4. selection sur une table en fonction de plusieurs ligne
    Par dimdidi dans le forum Langage SQL
    Réponses: 2
    Dernier message: 06/12/2004, 08h42
  5. Recupération des selections sur une DBGrille multi Selection
    Par Andry dans le forum Bases de données
    Réponses: 1
    Dernier message: 26/11/2004, 11h43

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