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 25/05/2011, 17h40   #1
Candidat au titre de Membre du Club
 
Inscription : avril 2004
Messages : 41
Détails du profil
Informations forums :
Inscription : avril 2004
Messages : 41
Points : 11
Points : 11
Par défaut tranformer des quantités en lignes

Bonjour,

J'ai un fichier d'articles dont une des colonnes correspond à la quantité d'articles.
Est-il possible et comment procéder pour obtenir une vue qui me duplique les articles en fonction de leur quantité respective par une requête SQL ?
(l'objectif est d'éditer des étiquettes.)

Merci.
msuire est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/05/2011, 18h22   #2
Responsable SQL Server

 
Avatar de mikedavem
 
Homme David BARBARIN
Expert SQL Server
Inscription : août 2005
Messages : 3 723
Détails du profil
Informations personnelles :
Nom : Homme David BARBARIN
Localisation : France, Haute Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Expert SQL Server
Secteur : Conseil

Informations forums :
Inscription : août 2005
Messages : 3 723
Points : 6 844
Points : 6 844
Pour l'avoir déja fait ... il vous faut une table de nombre supplémentaire pour réaliser cela.

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
29
30
31
32
-- Table des nombres
CREATE TABLE number
(
 idNumber INT PRIMARY KEY
);
 
-- Remplissage table des nombres
DECLARE @i INT = 1;
 
WHILE @i < 10000
BEGIN
 INSERT number VALUES (@i);
 
 SET @i += 1;
END
 
-- Table des articles
CREATE TABLE article
(
 code_article INT,
 description VARCHAR(50),
 qte INT
);
 
INSERT article VALUES (1, 'article1', 4);
INSERT article VALUES (2, 'article2', 3);
 
-- Duplication des lignes
SELECT A.*
FROM article AS A
INNER JOIN number AS NB
 ON NB.idNumber <= A.qte
++
mikedavem est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2011, 10h48   #3
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
à partir de la version 2005, avec une CTE recursive :

Code SQL :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
;WITH T AS( --jeu d'essai
	SELECT 'Article A' AS Art, 3 AS Qte
	UNION ALL
	SELECT 'Article B' , 5
	UNION ALL
	SELECT 'Article C', 2
),
Res AS (
	SELECT Art, Qte - 1 AS Qte
	FROM T
	WHERE Qte > 0
	UNION ALL
	SELECT Art, Qte - 1
	FROM Res
	WHERE Qte > 0
)
SELECT Art
FROM Res
ORDER BY Art
aieeeuuuuu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2011, 10h53   #4
Responsable SQL Server

 
Avatar de mikedavem
 
Homme David BARBARIN
Expert SQL Server
Inscription : août 2005
Messages : 3 723
Détails du profil
Informations personnelles :
Nom : Homme David BARBARIN
Localisation : France, Haute Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Expert SQL Server
Secteur : Conseil

Informations forums :
Inscription : août 2005
Messages : 3 723
Points : 6 844
Points : 6 844
Effectivement j'ai pensé à la méthode des CTE récursives mais je pense que si le nombre de lignes à traiter est important la méthode non récursive sera moins performante vu que l'on force un traitement ligne à ligne ... Après les performances ne sont pas forcément un problème dans ce contexte.

A voir



++
mikedavem est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2011, 11h23   #5
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
oui c'est vrai.

A tester en effet, l'idée étant d'avoir tout ça en une seule requête. mais un mix des deux serait :

Code SQL :
1
2
3
4
5
6
7
8
9
10
11
12
13
 
WITH Number(IdNumber) AS (
    SELECT MAX(Qte) 
    FROM Article
    UNION ALL
    SELECT IdNumber - 1
    FROM Number
    WHERE IdNumber > 1
)
SELECT A.*
FROM article AS A
INNER JOIN number AS NB
 ON NB.idNumber <= A.qte

Niveau perf, ça doit commencer à être pas mal
aieeeuuuuu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2011, 11h35   #6
Rédacteur/Modérateur

 
Avatar de WOLO Laurent
 
Homme Laurent WOLO
Architecte de base de données
Inscription : mars 2003
Messages : 2 696
Détails du profil
Informations personnelles :
Nom : Homme Laurent WOLO
Âge : 35
Localisation : Congo-Brazzaville

Informations professionnelles :
Activité : Architecte de base de données
Secteur : Finance

Informations forums :
Inscription : mars 2003
Messages : 2 696
Points : 3 917
Points : 3 917
Envoyer un message via Yahoo à WOLO Laurent
Citation:
Envoyé par mikedavem Voir le message
Pour l'avoir déja fait ... il vous faut une table de nombre supplémentaire pour réaliser cela.
Pour des raisons d'optimisation, Je propose de remplacer le code ci-dessous :
Code :
1
2
3
4
5
6
7
8
9
-- Remplissage table des nombres
DECLARE @i INT = 1;
 
WHILE @i < 10000
BEGIN
 INSERT number VALUES (@i);
 
 SET @i += 1;
END
++
Par celui-ci :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
WITH NombreCTE(N)
AS
(
    SELECT 0
    UNION SELECT 1
    UNION SELECT 2
    UNION SELECT 3
    UNION SELECT 4
    UNION SELECT 5
    UNION SELECT 6
    UNION SELECT 7
    UNION SELECT 8
    UNION SELECT 9
)
 
INSERT INTO number
SELECT 1000*M.N + 100*C.N + 10*D.N + U.N
FROM NombreCTE U 
				CROSS JOIN NombreCTE D
				CROSS JOIN NombreCTE C
				CROSS JOIN NombreCTE M
WHERE 1000*M.N + 100*C.N + 10*D.N + U.N BETWEEN 1 AND 9999
L'objectif est d'éviter les boucles et donc un gain de performances.
__________________

Découvrez la FAQ de MS SQL Server.
La chance accorde ses faveurs aux esprits avertis !
WOLO Laurent est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2011, 11h57   #7
Responsable SQL Server

 
Avatar de mikedavem
 
Homme David BARBARIN
Expert SQL Server
Inscription : août 2005
Messages : 3 723
Détails du profil
Informations personnelles :
Nom : Homme David BARBARIN
Localisation : France, Haute Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Expert SQL Server
Secteur : Conseil

Informations forums :
Inscription : août 2005
Messages : 3 723
Points : 6 844
Points : 6 844
Vous chipotez les gars là

La table number ne sera générée qu'une seule fois ici et sera utilisée par la suite pour dupliquer les lignes de la table cible. C'est juste une table de travail.

Mais tu as raison tant qu'à faire allons y jusqu'au bout :

Je propose encore plus simple pour créer la table des nombres :

Code :
1
2
3
SELECT IDENTITY(INT, 1,1) AS number INTO dbo.numbers
FROM master.dbo.spt_values
CROSS JOIN master.sys.objects
++
mikedavem est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2011, 14h05   #8
Rédacteur/Modérateur

 
Avatar de WOLO Laurent
 
Homme Laurent WOLO
Architecte de base de données
Inscription : mars 2003
Messages : 2 696
Détails du profil
Informations personnelles :
Nom : Homme Laurent WOLO
Âge : 35
Localisation : Congo-Brazzaville

Informations professionnelles :
Activité : Architecte de base de données
Secteur : Finance

Informations forums :
Inscription : mars 2003
Messages : 2 696
Points : 3 917
Points : 3 917
Envoyer un message via Yahoo à WOLO Laurent
Mikedavem, j'applique juste la théorie de Goering :
Il est mieux de faire de la pub sur les bonnes manières afin que tout le monde s'y habitue même s'ils vont le comprendre plus tard.

Par exemple je ne connaissais pas ta méthode plutôt très simple.
__________________

Découvrez la FAQ de MS SQL Server.
La chance accorde ses faveurs aux esprits avertis !
WOLO Laurent est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2011, 14h26   #9
Membre Expert
 
Avatar de iberserk
 
Homme Bruno IGNACE
Architecte de base de données
Inscription : novembre 2004
Messages : 1 299
Détails du profil
Informations personnelles :
Nom : Homme Bruno IGNACE
Âge : 30
Localisation : France, Gironde (Aquitaine)

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

Informations forums :
Inscription : novembre 2004
Messages : 1 299
Points : 2 282
Points : 2 282
Envoyer un message via MSN à iberserk
Personnellement je créerais la table de nombre et éviterez de faire des traitements répétitif inutile, qui plus est récursif...
__________________
Prendre conscience, c'est transformer le voile qui recouvre la lumière en miroir.
iberserk est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2011, 14h42   #10
Modérateur

 
Avatar de elsuket
 
Homme Nicolas Souquet
Administrateur de base de données
Inscription : janvier 2005
Messages : 4 669
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 669
Points : 8 729
Points : 8 729
Au passage, CROSS JOIN, en terme de performances, c'est pas terrible ...

@++
__________________
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 26/05/2011, 14h45   #11
Responsable SQL Server

 
Avatar de mikedavem
 
Homme David BARBARIN
Expert SQL Server
Inscription : août 2005
Messages : 3 723
Détails du profil
Informations personnelles :
Nom : Homme David BARBARIN
Localisation : France, Haute Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Expert SQL Server
Secteur : Conseil

Informations forums :
Inscription : août 2005
Messages : 3 723
Points : 6 844
Points : 6 844
Elsuket je t'ai rien d....................

++
mikedavem est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2011, 15h09   #12
Membre chevronné
 
Inscription : juillet 2006
Messages : 1 194
Détails du profil
Informations forums :
Inscription : juillet 2006
Messages : 1 194
Points : 746
Points : 746
Citation:
Envoyé par elsuket Voir le message
Au passage, CROSS JOIN, en terme de performances, c'est pas terrible ...

@++
Je pense le contraire donc quelle est votre réflexion ?
Sergejack est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2011, 15h20   #13
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
Citation:
Envoyé par iberserk Voir le message
Personnellement je créerais la table de nombre et éviterez de faire des traitements répétitif inutile, qui plus est récursif...
On peut même se passer de la table des nombres ET d'une CTE :


Code SQL :
1
2
3
4
5
6
7
8
9
10
11
 
SELECT A.*
FROM Article A
CROSS APPLY (
    SELECT TOP(A.qte) NULL AS X
    FROM Article B --ou n'importe quelle table qui contient des lignes
    CROSS JOIN Article C -- au grand dam d'Elsuket mais uniquement necessaire si COUNT(*) FROM Article < MAX(Qte)
    CROSS JOIN Article D --uniquement necessaire si count(*) ² < MAX(Qte)
    CROSS JOIN Article E --uniquement necess.. ok j'arrete ;)
    CROSS JOIN Article F -- ceinture et bretelles
) Z
aieeeuuuuu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2011, 16h13   #14
Rédacteur/Modérateur

 
Avatar de WOLO Laurent
 
Homme Laurent WOLO
Architecte de base de données
Inscription : mars 2003
Messages : 2 696
Détails du profil
Informations personnelles :
Nom : Homme Laurent WOLO
Âge : 35
Localisation : Congo-Brazzaville

Informations professionnelles :
Activité : Architecte de base de données
Secteur : Finance

Informations forums :
Inscription : mars 2003
Messages : 2 696
Points : 3 917
Points : 3 917
Envoyer un message via Yahoo à WOLO Laurent
Citation:
Envoyé par elsuket Voir le message
Au passage, CROSS JOIN, en terme de performances, c'est pas terrible ...

@++
Tu sais bien que c'est discutable et que nous n'allons pas nous affronter pour cela.
__________________

Découvrez la FAQ de MS SQL Server.
La chance accorde ses faveurs aux esprits avertis !
WOLO Laurent est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/05/2011, 17h19   #15
Membre chevronné
 
Inscription : juillet 2006
Messages : 1 194
Détails du profil
Informations forums :
Inscription : juillet 2006
Messages : 1 194
Points : 746
Points : 746
Citation:
Envoyé par WOLO Laurent Voir le message
Tu sais bien que c'est discutable et que nous n'allons pas nous affronter pour cela.
Sans affrontement, je suis curieux de l'alternative (bonne ou moins bonne) qu'y voyait Elsuket.
Sergejack 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 15h39.


 
 
 
 
Partenaires

Hébergement Web