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 17/01/2011, 11h49   #1
Membre actif
 
Avatar de Issam
 
Inscription : mars 2002
Messages : 347
Détails du profil
Informations personnelles :
Âge : 36

Informations forums :
Inscription : mars 2002
Messages : 347
Points : 177
Points : 177
Envoyer un message via Skype™ à Issam
Par défaut champs calculé dans la clause where

bonjour

est t'il possible d'avoir un champs calculé dans la clause where

le but est d'utiliser ce champs dans une comparaison "where" "between"

merci et bonne journée
Issam est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 13h26   #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
Bonjour,

La réponse est oui.

Si vous voulez nous donner plus de précisions sur votre probléme n'hésitez pas.

++
mikedavem est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 13h53   #3
Membre actif
 
Avatar de Issam
 
Inscription : mars 2002
Messages : 347
Détails du profil
Informations personnelles :
Âge : 36

Informations forums :
Inscription : mars 2002
Messages : 347
Points : 177
Points : 177
Envoyer un message via Skype™ à Issam
voila
pour simplifier
supposons que j'ai ces 3 tables :
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
 
CREATE TABLE ventes
(
  id_vente integer NOT NULL  PRIMARY KEY,
  VE_DATE date,
)
 
 
CREATE TABLE ventes_DETAILS
(
  id_vente_detail integer NOT NULL  PRIMARY KEY,
  VD_ID_VENTE integer, /* foreign key */
  VL_PRIX DECIMAL,
  VL_QTE DECIMAL
)
 
 
CREATE TABLE ventes_VERSEMENT
(
  id_versement integer NOT NULL  PRIMARY KEY,
  VER_ID_VENTE integer, /* foreign key */
  VER_DATE Date,
  VER_MONTANT decimal
)
ce que je voudrais afficher c'est les ventes qui on était payées que partiellement :
sum(versements) between sum(VL_PRIX * VL_QTE) pour cela j'ai utilisé cette requête :

Code :
1
2
3
4
5
6
SELECT DISTINCT VE.ID_VENTE, VE.VE_DATE , SUM(VD.VD_PRIX * VD.AD_QTE) AS MONTANT

FROM VENTES_DETAILS AS VD INNER JOIN VENTES AS VE ON VE.VD_ID_VENTE = VD.ID_VENTE 
WHERE (select sum(ver_montant) from versements where VER_ID_VENTE = VE.ID_VENTE) between 1 And MONTANT
GROUP BY VE.ID_VENTE, VE.VE_DATE, ORDER BY VE.VE_DATE DESC
malheureseument ça ne marche pas comme ça !
Issam est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 16h58   #4
Modérateur

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

Vous ne pouvez utiliser le alias de colonnes que dans une clause ORDER BY, c'et ce qui fait que votre requête ne fonctionne pas (MONTANT).

En outre, vous pouvez utiliser la clause HAVING de la clause GROUP BY :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
SELECT		V.ID_VENTE
		, V.VE_DATE
		, SUM(VD.VL_PRIX * VD.VL_QTE) AS montant_vente
		, SUM(VV.VER_MONTANT) AS montant_paye
FROM		dbo.VENTES_DETAILS AS VD
INNER JOIN	dbo.VENTES AS V
			ON VD.VD_ID_VENTE = V.ID_VENTE
INNER JOIN	dbo.VENTES_VERSEMENT AS VV
			ON VV.VER_ID_VENTE = V.ID_VENTE
GROUP BY	V.ID_VENTE
		, V.VE_DATE
HAVING		SUM(VV.VER_MONTANT) < SUM(VD.VL_PRIX * VD.VL_QTE)
Celle-ci vous permet de filtrer votre requête sur les valeurs d'un agrégat de celle-ci.

Vous pouvez aller plus loin en créant une vue indexée qui vous permettra d'optimiser et de simplifier l'expression de votre requête SQL, mais qui a un certain coût de maintenance.
C'est parfait si vos tables subissent des changements peu nombreux.
En revanche testez bien dans le cas contraire l'impact sur les performances.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
CREATE VIEW V_PAIEMENT_VENTES_PARTIEL
	WITH SCHEMABINDING
AS
SELECT		V.ID_VENTE
		, V.VE_DATE
		, SUM(VD.VL_PRIX * VD.VL_QTE) AS montant_vente
		, SUM(VV.VER_MONTANT) AS montant_paye
FROM		dbo.VENTES_DETAILS AS VD
INNER JOIN	dbo.VENTES AS V
			ON VD.VD_ID_VENTE = V.ID_VENTE
INNER JOIN	dbo.VENTES_VERSEMENT AS VV
			ON VV.VER_ID_VENTE = V.ID_VENTE
GROUP BY	V.ID_VENTE
		, V.VE_DATE
HAVING		SUM(VV.VER_MONTANT) < SUM(VD.VL_PRIX * VD.VL_QTE)
GO
 
CREATE CLUSTERED INDEX IXC__V_PAIEMENT_VENTES_PARTIEL
ON V_PAIEMENT_VENTES_PARTIEL(ID_VENTE)
GO
 
CREATE INDEX IXNC__V_PAIEMENT_VENTES_PARTIEL__VE_DATE
ON dbo.V_PAIEMENT_VENTES_PARTIEL(VE_DATE)
Il vous suffit alors d'écrire :

Code :
1
2
3
4
5
SELECT	ID_VENTE
	, VE_DATE
	, montant_vente
	, montant_paye
FROM	dbo.V_PAIEMENT_VENTES_PARTIEL
Pour obtenir les ventes partiellement payées.
Vous pouvez éventuellement filtrer par date :

Code :
1
2
3
4
5
6
SELECT	V.ID_VENTE
	, V.VE_DATE
	, montant_vente
	, montant_paye
FROM	dbo.V_PAIEMENT_VENTES_PARTIEL
WHERE VE_DATE > '20110101'
@++
__________________
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 17/01/2011, 16h58   #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
Bonjour

vous ne pouvez pas utiliser les alias de colonne pour élaborer votre filtres, car les filtres sont appliqués avant même l'évaluation des colonne spécifiées dans le SELECT. Vous devez donc respécifier la formule de calcul

D'autre part, vous utilisez une fonction d'agrégat, vous devez donc placer votre filtre dans une clause HAVING

Enfin, plutôt qu'une sous requete pour calculer la somme des versements, vous pouvez faire une jointure

Essayez ceci :


Code sql :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
SELECT 
  VE.ID_VENTE, 
  VE.VE_DATE , 
  SUM(VD.VD_PRIX * VD.AD_QTE) AS MONTANT,
  SUM(ver_montant) AS VERSE
FROM VENTES_DETAILS AS VD 
INNER JOIN VENTES AS VE 
  ON VE.VD_ID_VENTE = VD.ID_VENTE 
LEFT OUTER JOIN versement ver
  ON ver.VER_ID_VENTE = VE.IDVENTE)
GROUP BY VE.ID_VENTE, VE.VE_DATE, 
HAVING SUM(ver_montant) BETWEEN 1 AND SUM(VD.VD_PRIX * VD.AD_QTE)
ORDER BY VE.VE_DATE DESC
aieeeuuuuu est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 18/01/2011, 09h31   #6
Membre actif
 
Avatar de Issam
 
Inscription : mars 2002
Messages : 347
Détails du profil
Informations personnelles :
Âge : 36

Informations forums :
Inscription : mars 2002
Messages : 347
Points : 177
Points : 177
Envoyer un message via Skype™ à Issam
Merci tout le monde
Issam est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/01/2011, 10h27   #7
Membre actif
 
Avatar de Issam
 
Inscription : mars 2002
Messages : 347
Détails du profil
Informations personnelles :
Âge : 36

Informations forums :
Inscription : mars 2002
Messages : 347
Points : 177
Points : 177
Envoyer un message via Skype™ à Issam
Je relance le topic

maintenant que j'ai ma requete qui a l'air de marcher comme ceci
Code :
1
2
3
4
5
6
7
8
9
10
 
SELECT     AC.ID_ACHAT, AC.AC_DATE, SUM(AD.AD_PRIX * AD.AD_QTE) AS montant_vente, FR.FR_NOM, PT.ID_TYPE, SUM(VER.VER_MONTANT) 
                      AS montant_paye
FROM         ACHATS_DETAILS AS AD 
INNER JOIN   ACHATS AS AC ON AD.AD_ID_ACHAT = AC.ID_ACHAT 
INNER JOIN   FOURNISSEURS AS FR ON AC.AC_ID_FOURNISSEUR = FR.ID_FOURNISSEUR 
INNER JOIN  VERSEMENTS AS VER ON VER.VER_ID_ACHAT = AC.ID_ACHAT INNER JOIN   TYPES_PIECES AS PT ON AC.AC_TYPE_PIECE = PT.ID_TYPE
WHERE     (FR.FR_NOM = '%' + @FR_NOM + '%')
GROUP BY AC.ID_ACHAT, AC.AC_DATE, FR.FR_NOM, PT.ID_TYPE
HAVING      (SUM(VER.VER_MONTANT) BETWEEN 1 AND SUM(AD.AD_PRIX * AD.AD_QTE))
notez juste que cette requête concerne les achats et non pas les ventes
je voudrais ajouter d'autres fonctionnalités :

je voudrais avoir un indice de paiement dans le résultat si c'est possible,
je m’explique :

l'idéal c'est d'avoir une colonne de sortie qui aurait ces valeurs :
0 : quand SUM(VERSEMENTS) = 0;
1 : Quand SUM(VERSEMENTS) between 1 and sum(AD_PRIX * AD_QTE)
2 : quand SUM(VERSEMENTS) = sum(AD_PRIX * AD_QTE)
3 : quand SUM(VERSEMENTS) > sum(AD_PRIX * AD_QTE)

le but final c'est avoir un indice visuel dans mon UI

bonne journée
Issam est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/01/2011, 10h52   #8
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 Issam Voir le message
le but final c'est avoir un indice visuel dans mon UI
Alors fait le dans ton UI justement. C'est plus le role du programme de faire ce genre de choses. surtout que de toute façon tu devra quand même y faire un test pour afficher ton indice visuel en fonction...
Donc cette colonne supplémentaire est inutile

Enfin si tu y tiens vraiment, voici la syntaxe :
Code sql :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
SELECT     AC.ID_ACHAT, AC.AC_DATE, SUM(AD.AD_PRIX * AD.AD_QTE) AS montant_vente, FR.FR_NOM, PT.ID_TYPE, SUM(VER.VER_MONTANT) 
                      AS montant_paye
    CASE 
        WHEN SUM(VER.VER_MONTANT) = 0 THEN 0
        WHEN SUM(VER.VER_MONTANT) = sum(AD_PRIX * AD_QTE) THEN 2
        WHEN SUM(VER.VER_MONTANT) BETWEEN 1 AND sum(AD_PRIX * AD_QTE) THEN 1
        WHEN SUM(VER.VER_MONTANT) >  sum(AD_PRIX * AD_QTE) THEN 3
    END AS IndiceVisuel
FROM         ACHATS_DETAILS AS AD 
INNER JOIN   ACHATS AS AC ON AD.AD_ID_ACHAT = AC.ID_ACHAT 
INNER JOIN   FOURNISSEURS AS FR ON AC.AC_ID_FOURNISSEUR = FR.ID_FOURNISSEUR 
INNER JOIN  VERSEMENTS AS VER ON VER.VER_ID_ACHAT = AC.ID_ACHAT INNER JOIN   TYPES_PIECES AS PT ON AC.AC_TYPE_PIECE = PT.ID_TYPE
WHERE     (FR.FR_NOM = '%' + @FR_NOM + '%')
GROUP BY AC.ID_ACHAT, AC.AC_DATE, FR.FR_NOM, PT.ID_TYPE
HAVING      (SUM(VER.VER_MONTANT) BETWEEN 1 AND SUM(AD.AD_PRIX * AD.AD_QTE))

attention Le BETWEEN étant sur intervalle inclusif, il faut tester l'égalité avant le between. De même ton cas ne prend pas en compte les valeurs entre 0 et 1...
aieeeuuuuu est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 18/01/2011, 11h20   #9
Membre actif
 
Avatar de Issam
 
Inscription : mars 2002
Messages : 347
Détails du profil
Informations personnelles :
Âge : 36

Informations forums :
Inscription : mars 2002
Messages : 347
Points : 177
Points : 177
Envoyer un message via Skype™ à Issam
c'est exactement ce que je voulais

il me manquais la clause Case que je ne savait pas m'en servir

cette colonne est en effet un surplus qui me me permet de créer une simple fonction dans mon application (asp.net) qui prendrais un simple entier comme paramètre pour afficher l'image ou l'icone correspondante dans la grille de données

encore merci pour votre support
Issam 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 02h02.


 
 
 
 
Partenaires

Hébergement Web