Précédent   Forum des professionnels en informatique > Bases de données > MS SQL-Server
MS SQL-Server Forum Microsoft SQL-Server. Avant de poster -> FAQ SQL-Server, Tutoriels SQL-Server
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 14/02/2011, 15h59   #1
Membre à l'essai
 
Inscription : février 2011
Messages : 60
Détails du profil
Informations personnelles :
Localisation : France

Informations professionnelles :
Secteur : Industrie

Informations forums :
Inscription : février 2011
Messages : 60
Points : 21
Points : 21
Par défaut Tri des dates

Bonjour,

J'ai une table sous sql server sous cette forme:

code DEBTF FINTF DEBRD FINRD DEBRP FINRP DEBTX FINTX
111 2008-04-17 2008-07-01 2008-03-04 2008-06-30 2008-12-07 2009-01-04 2009-01-01 9999-12-31

Je souhaite avoir chaque fois la date la plus proche à la première colonne (DEBTF ) et qui est inférieure à la 2ème colonne ( FINTF).Si je traiterai cas par cas en comparant chaque fois les dates,je risque de ne pas prendre toutes les possibilités.

j'ai pensé à faire une procédure de tri sur les dates entre DEBTF et FINTF puisque à chaque fois je l'aurai besoin.

j'espère que mon problème est clair.
Merci d'avance pour des suggestions.Si c'est possible avec une tel procédure comment l'a définir.
AJ_ing est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/02/2011, 17h02   #2
Membre Expert
 
Homme
Développeur java, access, sql server
Inscription : octobre 2005
Messages : 851
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Val de Marne (Île de France)

Informations professionnelles :
Activité : Développeur java, access, sql server
Secteur : Industrie

Informations forums :
Inscription : octobre 2005
Messages : 851
Points : 1 302
Points : 1 302
Piste à suivre :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
SELECT *,
DateDiff(day,CONVERT(DateTime,DEBTF,120),CONVERT(DateTime,DateTest ,120)) AS NbJours
 FROM
(
SELECT code, DEBTF, FINTF, DEBRD AS DateTest FROM MaTable
UNION 
SELECT code, DEBTF, FINTF, FINRD AS DateTest FROM MaTable
UNION 
SELECT code, DEBTF, FINTF, DEBRP AS DateTest FROM MaTable
UNION 
SELECT code, DEBTF, FINTF, FINRP AS DateTest FROM MaTable
UNION 
SELECT code, DEBTF, FINTF, DEBTX AS DateTest FROM MaTable
UNION 
SELECT code, DEBTF, FINTF, FINTX AS DateTest FROM MaTable
) AS SousRequete
WHERE DateTest < FINTF
Méthode :
1) on empile ta table en 6 requêtes pour mettre toutes les dates à comparer dans la même colonne
2) on en profite pour éliminer les dates qui ne seraient pas < FINTF
3) NbJours est le nombre de jours séparant DateTest de DEBTF ce qui fait qu'il sera facile de trouver le minimum.
__________________
D'abord qu'il marche. Ensuite qu'il soit rapide. Enfin qu'il soit agréable à utiliser.
First, make it work. Then, make it fast. Finally, make it user-friendly.
Erst, mach', dass es funktioniert. Dann, mach', dass es schnell geht, Zum Schluss mach' es benutzerfreundlich.
Népomucène est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/02/2011, 17h51   #3
Modérateur

 
Avatar de elsuket
 
Homme Nicolas Souquet
Administrateur de base de données
Inscription : janvier 2005
Messages : 4 667
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 667
Points : 8 715
Points : 8 715
Bonjour,

Vous avez d'autres solutions :

- créer une fonction prenant en paramètre les 6 dates et extrayant la date la qui convient, et l'utiliser pour en faire une colonne calculée, éventuellement indexée

- Créer une vue indexée remplissant le même besoin

- Créer un trigger INSTEAD OF INSERT, UPDATE qui value une colonne supplémentaire pour vous. Moins performant ...

- Changer la conception de votre table en créant à la place une table qui stocke pour chaque code toutes les dates.
Cette table référencerait les 8 types de dates que vous stockez.
On aurait donc une table dont les colonnes seraient code, type_date, date.
La requête s'écrit alors très simplement en utilisant MIN, GROUP BY et HAVING.

Je pense que la dernière solution est, avec une bonne indexation, la meilleure en terme de conception et de performances

@++
__________________
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 15/02/2011, 13h19   #4
Membre à l'essai
 
Inscription : février 2011
Messages : 60
Détails du profil
Informations personnelles :
Localisation : France

Informations professionnelles :
Secteur : Industrie

Informations forums :
Inscription : février 2011
Messages : 60
Points : 21
Points : 21
Bonjour à tous,

Merci pour vos suggestions.
Je choisis cette solution :
Citation:
créer une fonction prenant en paramètre les 6 dates et extrayant la date la qui convient, et l'utiliser pour en faire une colonne calculée, éventuellement indexée
.

Mais j'ai pas bien compris comment je ferai l'extraction de la date et la colonne à créer.Pouvez vous m'expliquez de plus.

Merci.
AJ_ing est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2011, 14h04   #5
Modérateur

 
Avatar de elsuket
 
Homme Nicolas Souquet
Administrateur de base de données
Inscription : janvier 2005
Messages : 4 667
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 667
Points : 8 715
Points : 8 715
Donc voici la fonction :

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
CREATE FUNCTION myFunction
	(
		@_DEBTF datetime
		, @_FINTF datetime
		, @_DEBRD datetime
		, @_FINRD datetime
		, @_DEBRP datetime
		, @_FINRP datetime
		, @_DEBTX datetime
		, @_FINTX datetime
	)
	RETURNS datetime
AS
BEGIN
	RETURN
	(
		SELECT	MIN(min_date)
		FROM	(
				SELECT @_DEBRD AS min_date
				UNION ALL SELECT @_FINRD
				UNION ALL SELECT @_DEBRP
				UNION ALL SELECT @_FINRP
				UNION ALL SELECT @_DEBTX
				UNION ALL SELECT @_FINTX
			) AS T
		WHERE min_date BETWEEN @_DEBTF AND @_FINTF
	)
END
GO
Que j'ai testé avec plusieurs dates entre @_DEBTF et @_FINTF pour être certain que c'est bien ce que vous voulez.

Ensuite je me suis créé la table suivante :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
CREATE TABLE test
(
	code int
	, DEBTF datetime
	, FINTF datetime
	, DEBRD datetime
	, FINRD datetime
	, DEBRP datetime
	, FINRP datetime
	, DEBTX datetime
	, FINTX datetime
)
Et je lui ai ajouté la colonne calculée ZeDate comme suit :

Code :
1
2
ALTER TABLE dbo.test
ADD ZeDate AS(dbo.myFunction(DEBTF, FINTF, DEBRD, FINRD, DEBRP, FINRP, DEBTX, FINTX))
Un petit test :

Code :
INSERT	dbo.test VALUES (111, '2008-04-17', '2008-07-01', '2008-03-04', '2008-06-30', '2008-12-07', '2009-01-04', '2009-01-01', '9999-12-31')
Puis
Code :
1
2
SELECT	*
FROM	dbo.test
Qui donne :

Citation:
code DEBTF FINTF DEBRD FINRD DEBRP FINRP DEBTX FINTX ZeDate
111 2008-04-17 00:00:00.000 2008-07-01 00:00:00.000 2008-03-04 00:00:00.000 2008-06-30 00:00:00.000 2008-12-07 00:00:00.000 2009-01-04 00:00:00.000 2009-01-01 00:00:00.000 9999-12-31 00:00:00.000 2008-06-30 00:00:00.000
Notez que vous pouvez indexer la colonne calculée (même si elle n'est pas persistée, ce qui et le cas puisque la fonction n'est pas déterministe) si vous devez à l'avenir écrire des requêtes filtrées sur cette colonne.

@++
__________________
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 22/02/2011, 10h21   #6
Membre à l'essai
 
Inscription : février 2011
Messages : 60
Détails du profil
Informations personnelles :
Localisation : France

Informations professionnelles :
Secteur : Industrie

Informations forums :
Inscription : février 2011
Messages : 60
Points : 21
Points : 21
Bonjour,

Merci ça bien marché.

Comment rendre cette fonction retournant Min et @DEBTF

Le fait d'ajouter un champ dans le select me pause le problème suivant:

Code :
Only one expression can be specified IN the SELECT list when the subquery IS NOT introduced WITH EXISTS.
Cordialement.
AJ_ing est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/02/2011, 12h44   #7
Modérateur

 
Avatar de elsuket
 
Homme Nicolas Souquet
Administrateur de base de données
Inscription : janvier 2005
Messages : 4 667
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 667
Points : 8 715
Points : 8 715
C'est normal puisque nous avons écrit :
La fonction est donc une fonction scalaire, et ne retourne donc qu'une valeur (pas une table !).

Si vous voulez ajouter une colonne, vous devez modifier la fonction pour qu'elle fasse 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
ALTERFUNCTION myFunction
	(
		@_DEBTF datetime
		, @_FINTF datetime
		, @_DEBRD datetime
		, @_FINRD datetime
		, @_DEBRP datetime
		, @_FINRP datetime
		, @_DEBTX datetime
		, @_FINTX datetime
	)
	RETURNS TABLE
AS
	RETURN
	(
		SELECT	MIN(min_date) AS min_date
			, @_DEBTF AS DEBTF
		FROM	(
				SELECT @_DEBRD AS min_date
				UNION ALL SELECT @_FINRD
				UNION ALL SELECT @_DEBRP
				UNION ALL SELECT @_FINRP
				UNION ALL SELECT @_DEBTX
				UNION ALL SELECT @_FINTX
			) AS T
		WHERE min_date BETWEEN @_DEBTF AND @_FINTF
	)
GO
Dès lors vous ne pourrez pas l'utiliser pour définir une colonne calculée, ni l'appeler dans une requête avant le FROM, ou après le WHERE.

Vous pourrez en revanche l'utiliser avec l'opérateur APPLY.
SI vous ne voulez retourner que les lignes pour lesquelles la fonction retourne une valeur, utilisez CROSS APPLY.
Si en revanche vous voulez les deux colonnes retournées par APPLY, qu'il existe un résultat ou non (les deux colonnes de la fonction sont donc à NULL), utiliser OUTER APPLY.

Si vous ne voyez pas comment écrire une telle requête, donnez votre requête actuelle (ou son squelette) et ce que vous souhaitez obtenir en sortie.

@++
__________________
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 22/02/2011, 14h45   #8
Membre à l'essai
 
Inscription : février 2011
Messages : 60
Détails du profil
Informations personnelles :
Localisation : France

Informations professionnelles :
Secteur : Industrie

Informations forums :
Inscription : février 2011
Messages : 60
Points : 21
Points : 21
Bonjour,

Merci bien,

j'ai pris info de ces deux lien sur l'intra jointure Apply:

http://blog.developpez.com/sqlpro/p9...ointure-apply/

http://technet.microsoft.com/fr-fr/l...6(SQL.90).aspx

AJ_ing 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 10h38.


 
 
 
 
Partenaires

Hébergement Web