كيف أقوم بإنشاء استعلام SQL واحد للحصول على قيم MTD وYTD في نفس الصف؟


لدي تقرير Crystal Report الذي أقوم بتحويله إلى SSRS حاليًا. يحتوي هذا التقرير على 3 أعمدة لـ MTD (قيم الشهر حتى التاريخ) و3 أعمدة لـ YTD (قيم السنة حتى التاريخ). أنا قادر على فصل هذه الأعمدة الثلاثة ولكن من أجل دقة البيانات أحتاج إلى دمجها في عبارة SQL واحدة لإخراجها في صف واحد. لقد تمكنت من الاقتراب منه تقريبًا باستخدام بعض وظائف الدمج في SQL. تكمن المشكلة في أنه لن يسمح لي باستخدام المجموعة حسب الأوامر ويؤدي إلى حدوث خطأ. ما الذي يجب أن أقوم بتحريره في استعلام SQL الخاص بي بالطريقة التي تظهر في تقرير Crystal Report أدناه؟
خطأ :

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.

تقرير Crystal الحالي الذي أقوم بتحويله إلى SSRS

تحرير: لقد قمت للتو بإنشاء نموذج dbfiddle : DB Fiddle – ملعب قاعدة بيانات SQL[^]

لقد حاولت في الكود 2 استخدام البعض مع والنقابات ولكنه يعطيني بعض الأخطاء مثل

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.

ما حاولت:

الكود 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

الكود 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;

الحل 1

في حالة عدم وجود أي بيانات نموذجية، ابدأ بمعالجة هذه النقاط.

– 100.dbo.IS_vwSalesbyProductLineComp ليس معرف SQL صالحًا. يجب أن تبدأ معرفات SQL بحرف أو الشرطة السفلية

– لا تحتاج إلى تأهيل اسم الجدول في الأعمدة في حالة الاختيار من جدول واحد فقط

– إذا كنت ستقوم بتأهيل الأعمدة، فاستخدم الأسماء المستعارة بدلاً من اسم الجدول الكامل لجعل البرنامج النصي أكثر قابلية للقراءة، على سبيل المثال بدلاً من

SQL
select IS_vwSalesbyProductLineComp.sls_amt
from IS_vwSalesbyProductLineComp

يستخدم

SQL
select splc.sls_amt 
from IS_vwSalesbyProductLineComp splc

— تخلص من المحددات الموجودة في أسماء الأعمدة والجداول – فهي ليست ضرورية وتجعل استعلامك غير قابل للقراءة

– إذا كنت تستخدم المحددات فاستخدمها [ ] أي بدلا من "IS_vwSalesbyProductLineComp" يستخدم [IS_vwSalesbyProductLineComp] – مرة أخرى، إنه أكثر قابلية للقراءة

— إفادتكم

يقتبس:

ولكن من أجل دقة البيانات أحتاج إلى دمجها في عبارة SQL واحدة

غير صالح. عدد عبارات SQL المستخدمة ليس له أي تأثير على دقة البيانات. قد يكون الهوس بجمع كل شيء في عبارة واحدة ضارًا بالوضوح والدقة (في البرنامج النصي الخاص بك، وليس البيانات) والأداء.

– ليست هناك حاجة مطلقًا لكل هذه الاستعلامات الفرعية – بالإضافة إلى ذلك، كما رأيت، فإنك تحصل على عدة صفوف مرة أخرى

احصل على جميع البيانات التي تحتاجها في صفوف منفصلة – إذا كنت تصر على أن تكون عبارة SQL واحدة، فاستخدم تعبير الجدول العام (CTE -) مع common_table_expression (Transact-SQL) – SQL Server | مستندات مايكروسوفت[^] ).

ثم المحورية تلك النتائج للحصول على الجدول الذي تريده – راجع شرح مشغل SQL Server PIVOT بوضوح من خلال الأمثلة العملية[^]

الحل 2

للوهلة الأولى…استفسارك سيء حقًا:
الخطأ الأهم هو: عدد كبير جدًا من التحديدات!
لقد حصلت على 1 رئيسي SELECT ثم 4 فرعيةSELECT!

حاول إعادة كتابة الاستعلام الخاص بك لتتمكن من استخدام عدد أقل من SELECT.
تحقق من كل استعلام فرعي واحد. إذا قام أي منها بإرجاع أكثر من سجل واحد، فيجب عليك تحسين هذا الاستعلام.

وفي هذه الأثناء، من فضلك، اقرأ هذا: إصلاح الرسالة 512 “أرجع الاستعلام الفرعي أكثر من قيمة واحدة” في SQL Server[^]

الحل 5

https://www.google.com/search?q=standale+to+Hometown+Water+Fire+Restoration
مشاركة رائعة ولكن كنت أتساءل عما إذا كان بإمكانك كتابة المزيد حول هذا الموضوع؟
سأكون ممتنًا جدًا إذا أمكنك توضيح المزيد.

هتافات!

コメント

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