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 30/05/2011, 18h46   #1
Futur Membre du Club
 
Inscription : décembre 2010
Messages : 125
Détails du profil
Informations forums :
Inscription : décembre 2010
Messages : 125
Points : 19
Points : 19
Par défaut SQL SERVER 2005 - Group by + Cumul

Bonjour,

veuillez trouver en pièce jointe mon 'problème'.
J'ai une table avec 2 colonnes : date et type (tableau de gauche)

J'ai déja une requete qui me permet de grouper par date, et me donner le nombre de types différents pour chacune des dates (tableau du milieu).

J'aimerai maintenant trouver une requete qui me permet de grouper par date, et me donner le cumul des differents types.
- C'est a dire que pour le 01.01.2011, j'ai 3 types différents
- Pour le 02.01.2011, j'ai 3 types différents depuis le 01.01.2011 jusqu'au 02.01.2011
- Pour le 03.01.2011, j'ai 5 types différents depuis le 01.01.2011 jusqu'a 03.01.2011.
- Ainsi de suite.

J'ai donc besoin de valeur unique, cumuléee..

J'espère avoir bien explicité mon problème.

Merci d'avance.
Images attachées
Type de fichier : png Capture d’écran 2011-05-30 à 18.37.33.png (24,9 Ko, 11 affichages)
apnw7931 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/05/2011, 03h38   #2
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
Bonjour,

Voici :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
;WITH
	CTE AS
	(
		SELECT	DISTINCT [date]
			, (
				SELECT	DISTINCT [type] + ','
				FROM	dbo.maTable AS S
				WHERE	S.date = T.date
				FOR XML PATH('')
			) AS cumul
		FROM	dbo.maTable AS T
	)
SELECT	date
	, LEFT(cumul, LEN(cumul) - 1) AS cumul
FROM	CTE
@++
__________________
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 10
Vieux 31/05/2011, 08h54   #3
Futur Membre du Club
 
Inscription : décembre 2010
Messages : 125
Détails du profil
Informations forums :
Inscription : décembre 2010
Messages : 125
Points : 19
Points : 19
Merci pour cette proposition.

Par contre, je souhaite avoir le nombre du cumul (pas les différents types cumulés). Il me faut donc la deuxième colonne dans mon exemple (dont le nombre augmenterait jour apres jours). La troisième ne servait qu'a explicité mon souhait.

Pourriez-vous corriger votre code ? A défaut, je vais essayer de chipoter un peu de mon coté..


Merci d'avance.

je suppose que je dois modifier ainsi:
Code :
1
2
3
4
 
SELECT	DISTINCT COUNT([type])
FROM	dbo.maTable AS S
WHERE	S.date = T.date
apnw7931 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/05/2011, 09h10   #4
Membre chevronné
 
Inscription : juillet 2006
Messages : 1 194
Détails du profil
Informations forums :
Inscription : juillet 2006
Messages : 1 194
Points : 746
Points : 746
Code :
1
2
3
4
5
6
7
8
9
10
11
 
SELECT 
T1.Date, COUNT(*)
FROM (
 SELECT DISTINCT DATE
 FROM maTable
) AS T1(Date)
INNER JOIN maTable AS T2 ON (
 T2.Date <= T1.Date
)
GROUP BY T1.Date
Sergejack est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/05/2011, 09h16   #5
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
Voici :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
;WITH
	CTE AS
	(
		SELECT	[date]
			, COUNT(DISTINCT [type]) AS distinct_count
			, (
				SELECT	DISTINCT [type] + ','
				FROM	dbo.maTable AS S
				WHERE	S.date = T.date
				FOR XML PATH('')
			) AS cumul
		FROM	dbo.maTable AS T
		GROUP	BY [date]
	)
SELECT	date
	, distinct_count
	, LEFT(cumul, LEN(cumul) - 1) AS cumul
FROM	CTE
En ce qui concerne FOR XML PATH, l'ajout de cette clause permet normalement de retourner un document XML formé à partir du résultat de la requête, et donc chaque élément est qualifié par un nœud dont le nom est celui de la colonne dont est issue la valeur.

Dans la requête, je force le nom de la colonne à "chaîne vide", donc je n'ai que des éléments <type>.
Comme j'ai cumulé la valeur avec une virgule (+ ', '), le nœud type n'existe pas, et j'ai donc seulement les valeurs trouvées dans la colonne.

C'est une petite astuce qui est la plus légère (en temps d'exécution et en consommation de ressources) lorsqu'on souhaite "cumuler" des valeurs comme ici.

En revanche c'est bien sûr anti-relationnel.

@++
__________________
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 31/05/2011, 09h19   #6
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
SergeJack, votre requête retourne un total cumulé des occurrences ...

@++
__________________
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 31/05/2011, 09h47   #7
Futur Membre du Club
 
Inscription : décembre 2010
Messages : 125
Détails du profil
Informations forums :
Inscription : décembre 2010
Messages : 125
Points : 19
Points : 19
Citation:
Envoyé par elsuket Voir le message
Voici :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
;WITH
	CTE AS
	(
		SELECT	[date]
			, COUNT(DISTINCT [type]) AS distinct_count
			, (
				SELECT	DISTINCT [type] + ','
				FROM	dbo.maTable AS S
				WHERE	S.date = T.date
				FOR XML PATH('')
			) AS cumul
		FROM	dbo.maTable AS T
		GROUP	BY [date]
	)
SELECT	date
	, distinct_count
	, LEFT(cumul, LEN(cumul) - 1) AS cumul
FROM	CTE
-
Ce code ci ne me cumule pas mes valeurs..
J'obtiens exactement les memes résultats avec mon code ci dessous :

Code :
1
2
3
4
SELECT	 date, COUNT(DISTINCT type)
FROM	 EP0126A_104
WHERE	 datebetween '20110103' AND '201101005'
GROUP BY date
Qu'est-ce qui cloche ?
apnw7931 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/05/2011, 09h54   #8
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
Dans ce cas j'ai du mal comprendre, et la requête de SergeJack est correcte.
Je pensais que vous parliez du champ Distinct de votre fichier Excel.

Pouvez-vous donner le nom du champ de votre fichier Excel que vous souhaitez voir cumulé ?

@++
__________________
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 31/05/2011, 10h00   #9
Futur Membre du Club
 
Inscription : décembre 2010
Messages : 125
Détails du profil
Informations forums :
Inscription : décembre 2010
Messages : 125
Points : 19
Points : 19
Merci elsuket et SergeJack pour votre aide :-)

Pour clarifier, dans mon fichier excel (car je pense que le mot 'cumul' porte à confusion, désolé)
- le premier tableau correspond à ma table;
- le deuxième tableau correspond aux valeurs distinctes, par jour, que j'obtiens facilement avec ce code:

Code :
1
2
3
4
SELECT	 tdproddate, COUNT(DISTINCT c_account_number)
FROM	 MA_TABLE
WHERE	 tdproddate BETWEEN '20110103' AND '20110105'
GROUP BY tdproddate
- le troisième tableau est celui dont j'ai besoin.
Ainsi, j'ai besoin :
- pour ma premiere date, toutes les valeurs distinctes (c_account_number) de ce jour
- pour ma deuxième date, toutes les valeurs distinctes (c_account_number) entre le premier jour et celui-ci
- pour ma troisième date, toutes les valeurs distinctes (c_account_number) entre le premier jour et celui-ci (le troisième jour)

etc..


Pour le code de SergeJack, j'ai encore quelques difficultés à l'implémenter dans mon code.. (ca me donne des valeurs bcp trop grandes) j'essaye..
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT 
T1.tdproddate, COUNT(DISTINCT c_account_number)
FROM (
 SELECT DISTINCT tdproddate
 FROM MA_TABLE
) AS T1(tdproddate)
INNER JOIN MA_TABLE AS T2 ON (
 T2.tdproddate <= T1.tdproddate
)
 
WHERE	 t1.tdproddate BETWEEN '20110503' AND '20110503'
 
GROUP BY T1.tdproddate
apnw7931 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/05/2011, 10h30   #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
Je me trompe ou vous devez calculer ce résultat pour le montrer dans un rapport ou quelque chose dans le style ?

Si c'est le cas, il vaudrait mieux coder cela côté applicatif ...
SQL n'est pas un langage de présentation de données.

@++
__________________
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 31/05/2011, 10h37   #11
Futur Membre du Club
 
Inscription : décembre 2010
Messages : 125
Détails du profil
Informations forums :
Inscription : décembre 2010
Messages : 125
Points : 19
Points : 19
Citation:
Envoyé par elsuket Voir le message
Je me trompe ou vous devez calculer ce résultat pour le montrer dans un rapport ou quelque chose dans le style ?
En effet, la finalité serait d'exporter les résultats dans Excel, et d'y faire des calculs.

MAIS.... j'ai finalement réussi à coder ce dont j'avais besoin, comme suit:

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT
 a.tdproddate AS [Date],
 COUNT(DISTINCT a.c_account_number) AS [Daily],
 (	SELECT	 COUNT(DISTINCT b.c_account_number)
	FROM	 MA_TABLE AS b
	WHERE	 b.tdproddate BETWEEN '20110103' AND a.tdproddate
 ) AS [UNIQUE]
 
FROM	 MA_TABLE AS a
 
WHERE	 tdproddate BETWEEN '20110103' AND '20110105'
 
GROUP BY tdproddate
Merci à vous pour vos contributions et idées.
apnw7931 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 17h28.


 
 
 
 
Partenaires

Hébergement Web