Comment créer une requête SQL pour avoir les valeurs MTD et YTD sur la même ligne ?

la programmation


J’ai un Crystal Report que je convertis actuellement en SSRS. Ce rapport comporte 3 colonnes pour MTD (valeurs cumulées du mois) et 3 colonnes pour le cumul annuel (valeurs cumulées de l’année). Je suis capable de séparer ces 3 colonnes, mais pour l’exactitude des données, je dois les combiner dans une seule instruction SQL pour afficher sur une seule ligne. J’ai pu m’en rapprocher presque en utilisant certaines fonctions de fusion dans SQL. Le problème est que cela ne me permet pas d’utiliser les commandes group by et me renvoie une erreur. Que dois-je modifier dans ma requête SQL comme indiqué dans le rapport Crystal ci-dessous ?
Erreur :

Msg 512, Level 16, State 1, Line 106
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

Rapport Crystal actuel que je convertis en SSRS

EDIT : je viens de créer un exemple de dbfiddle : DB Fiddle – Terrain de jeu de base de données SQL[^]

Dans le Code 2, j’ai essayé d’en utiliser avec et les syndicats mais cela me donne une erreur car

Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.

Ce que j’ai essayé :

Codage 1

SQL
SET ARITHABORT OFF
SET ANSI_WARNINGS OFF
SELECT coalesce((Select ((SUM( "IS_vwSalesbyProductLineComp"."sls_amt")-SUM( "IS_vwSalesbyProductLineComp"."cost_amt"))/SUM( "IS_vwSalesbyProductLineComp"."sls_amt"))*100 ),0) AS G1MTD,
	   "IS_vwSalesbyProductLineComp"."Mainslspsn_name",
	   "IS_vwSalesbyProductLineComp"."PCSummarized",
	   coalesce ((SELECT SUM("IS_vwSalesbyProductLineComp"."qty_to_ship"-"IS_vwSalesbyProductLineComp"."qty_return_to_stk")FROM "100"."dbo"."IS_vwSalesbyProductLineComp"
   where Year = 2021
   and Month between 1 and 12 Group by Mainslspsn_name,PCSummarized),0) AS Qty_Sold,
	   coalesce ((SELECT SUM("IS_vwSalesbyProductLineComp"."sls_amt")FROM "100"."dbo"."IS_vwSalesbyProductLineComp"
   where Year = 2021
   and Month between 1 and 12 Group by Mainslspsn_name,PCSummarized),0) AS YTD_Sales,
	   coalesce ((SELECT SUM("IS_vwSalesbyProductLineComp"."cost_amt")FROM "100"."dbo"."IS_vwSalesbyProductLineComp"
   where Year = 2021
   and Month between 1 and 12 Group by Mainslspsn_name,PCSummarized),0) AS YTD_COGS,
	   coalesce((Select ((SUM( "IS_vwSalesbyProductLineComp"."sls_amt")-SUM( "IS_vwSalesbyProductLineComp"."cost_amt"))/SUM( "IS_vwSalesbyProductLineComp"."sls_amt"))*100 
	   FROM "100"."dbo"."IS_vwSalesbyProductLineComp"
   where Year = 2021
   and Month between 1 and 12 Group by Mainslspsn_name,PCSummarized),0) AS G2YTD,
		SUM("IS_vwSalesbyProductLineComp"."qty_to_ship"-"IS_vwSalesbyProductLineComp"."qty_return_to_stk") 
		AS Qty_Sold,
   		SUM("IS_vwSalesbyProductLineComp"."sls_amt") 
		AS MTD_Sales,
      	SUM("IS_vwSalesbyProductLineComp"."cost_amt") 
		AS MTD_COGS   
   FROM "100"."dbo"."IS_vwSalesbyProductLineComp"
   where Year = 2021
   and Month = 12
   Group by Mainslspsn_name,PCSummarized
   order by PCSummarized

Codage 2

SET ARITHABORT OFF
SET ANSI_WARNINGS OFF
WITH 
T1 AS
(
SELECT (
       SELECT((SUM(IS_vwSalesbyProductLineComp.sls_amt) - SUM(IS_vwSalesbyProductLineComp.cost_amt)) / SUM(IS_vwSalesbyProductLineComp.sls_amt)) * 100) AS G1MTD, 
       IS_vwSalesbyProductLineComp.Mainslspsn_name, 
       IS_vwSalesbyProductLineComp.PCSummarized, 
       (
       SELECT SUM(IS_vwSalesbyProductLineComp.qty_to_ship - IS_vwSalesbyProductLineComp.qty_return_to_stk)
       FROM "100".dbo.IS_vwSalesbyProductLineComp
       WHERE Year = 2021
             AND Month BETWEEN 1 AND 12
       GROUP BY Mainslspsn_name, 
                PCSummarized) AS Qty_Sold, 
       (
       SELECT SUM(IS_vwSalesbyProductLineComp.sls_amt)
       FROM "100".dbo.IS_vwSalesbyProductLineComp
       WHERE Year = 2021
             AND Month BETWEEN 1 AND 12
       GROUP BY Mainslspsn_name, 
                PCSummarized) AS YTD_Sales, 
      (
       SELECT SUM(IS_vwSalesbyProductLineComp.cost_amt)
       FROM "100".dbo.IS_vwSalesbyProductLineComp
       WHERE Year = 2021
             AND Month BETWEEN 1 AND 12
       GROUP BY Mainslspsn_name, 
                PCSummarized) AS YTD_COGS, 
       (
       SELECT((SUM(IS_vwSalesbyProductLineComp.sls_amt) - SUM(IS_vwSalesbyProductLineComp.cost_amt)) / SUM(IS_vwSalesbyProductLineComp.sls_amt)) * 100
       FROM "100".dbo.IS_vwSalesbyProductLineComp
       WHERE Year = 2021
             AND Month BETWEEN 1 AND 12
       GROUP BY Mainslspsn_name, 
                PCSummarized) AS G2YTD, 
       SUM(IS_vwSalesbyProductLineComp.qty_to_ship - IS_vwSalesbyProductLineComp.qty_return_to_stk) AS Qty_Sold2, --> renamed because ambigous
       SUM(IS_vwSalesbyProductLineComp.sls_amt) AS MTD_Sales, 
       SUM(IS_vwSalesbyProductLineComp.cost_amt) AS MTD_COGS
FROM "100".dbo.IS_vwSalesbyProductLineComp
WHERE Year = 2021
      AND Month = 12
GROUP BY Mainslspsn_name, 
         PCSummarized
),
T2 AS 
(
SELECT 0 AS C1, '' AS C2, '' AS C3, 0 AS C4, 0 AS C5, 0 AS C6, 0 AS C7, 0 AS C8, 0 AS C9, 0 AS C10
),
T3 AS
(
SELECT * FROM T1
UNION 
SELECT * FROM T2
)
SELECT SUM(G1MTD) AS G1MTD, 
   (SELECT [text()] = Mainslspsn_name
       FROM "100".dbo.IS_vwSalesbyProductLineComp 
       FOR XML 
           PATH(''),
           TYPE
   ).value
     (
         './text()[1]', 
         'nvarchar(max)'
     ),
   (SELECT [text()] = PCSummarized
       FROM "100".dbo.IS_vwSalesbyProductLineComp 
       FOR XML 
           PATH(''),
           TYPE
   ).value
     (
         './text()[1]', 
         'nvarchar(max)'
     ),
       SUM(Qty_Sold) AS Qty_Sold,
       SUM(YTD_Sales) AS YTD_Sales,
       SUM(YTD_COGS) AS YTD_COGS,
       SUM(G2YTD) AS G2YTD,
       SUM(Qty_Sold2) AS Qty_Sold2,
       SUM(MTD_Sales) AS MTD_Sales,
       SUM(MTD_COGS) AS MTD_COGS
FROM T3
GROUP BY Mainslspsn_name, 
         PCSummarized
ORDER BY PCSummarized;

Solution 1

En l’absence de tout échantillon de données, commencez par aborder ces points.

— 100.dbo.IS_vwSalesbyProductLineComp n’est pas un identifiant SQL valide. Les identifiants SQL doivent commencer par une lettre ou un trait de soulignement

— vous n’avez pas besoin de qualifier le nom de la table dans les colonnes si vous ne sélectionnez que dans une seule table

— si vous voulez qualifier les colonnes, utilisez des alias au lieu du nom complet de la table pour rendre le script plus lisible, par exemple au lieu de

SQL
select IS_vwSalesbyProductLineComp.sls_amt
from IS_vwSalesbyProductLineComp

utiliser

SQL
select splc.sls_amt 
from IS_vwSalesbyProductLineComp splc

— supprimez les délimiteurs sur les noms de colonnes et de tables – ils ne sont pas nécessaires et rendent simplement votre requête illisible

— Si vous utilisez des délimiteurs, utilisez [ ] c’est à dire au lieu de "IS_vwSalesbyProductLineComp" utiliser [IS_vwSalesbyProductLineComp] – encore une fois, c’est plus lisible

— votre déclaration

Citation:

mais pour l’exactitude des données, je dois les combiner dans une seule instruction SQL

n’est pas valide. Le nombre d’instructions SQL utilisées n’a aucune incidence sur l’exactitude des données. Être obsédé par l’idée de tout regrouper dans une seule instruction peut nuire à la clarté, à l’exactitude (de votre script, pas des données) et aux performances.

— il n’est absolument pas nécessaire de toutes ces sous-requêtes – de plus, comme vous l’avez vu, vous récupérez plusieurs lignes

Obtenez toutes les données dont vous avez besoin dans des lignes séparées – si vous insistez pour qu’il s’agisse d’une seule instruction SQL, utilisez une expression de table commune (CTE – AVEC expression_table_commune (Transact-SQL) – SQL Server | Microsoft Docs[^] ).

Alors PIVOT ces résultats pour obtenir la table que vous voulez – voir Opérateur PIVOT SQL Server expliqué clairement par des exemples pratiques[^]

Solution 2

À première vue… votre requête est vraiment mauvaise :
L’erreur la plus importante est : trop de SELECT!
Vous avez 1 principal SELECT puis 4 sous-SELECT!

Essayez de réécrire votre requête pour pouvoir utiliser moins de SELECT.
Découvrez chaque sous-requête. Si l’un d’entre eux renvoie plus d’un enregistrement, vous devez améliorer cette requête.

En attendant, lisez ceci : Correction du message 512 « La sous-requête a renvoyé plus d’une valeur » dans SQL Server[^]

Solution 5

https://www.google.com/search?q=standale+to+Hometown+Water+Fire+Restoration
Excellent article cependant, je me demandais si vous pouviez écrire un peu plus sur ce sujet ?
Je vous serais très reconnaissant si vous pouviez développer un peu plus.

Acclamations!

コメント

タイトルとURLをコピーしました