sql - 如何使用具有多列的 SQL 获取小计?
问题描述
希望生成一份关于销售订单和销售报价的报告,该报告对每个报价和订单进行分组和汇总以提供小计。
它应该为组合在一起的“文档编号”(订单/报价)总计“行金额”。
也可以得到一个总计但不是 100% 的要求。
我曾尝试使用ROLLUP
它来制作它,但没有成功。
SELECT
CONVERT (VARCHAR(12),SH.[Order Date],107) AS [Posting Date],
SH.[Salesperson] AS [Sales Staff],
SH.[No_] AS [Document No],
SH.[Customer No_] AS [Cust. No.],
SH.[Customer Name] AS [Customer Name],
SH.[Country] AS [Country],
CONVERT (Decimal(10,0),SL.[Quantity]) AS [Qty.],
SL.[Unit of Measure] AS [UOM],
SL.[No_] AS [Product No.],
SL.[Description] AS [Product Description],
CONVERT (Decimal(10,2),SL.[Unit Price]) AS [Unit Price],
SUM (CONVERT (Decimal(10,2),SL.[Line Amount])) AS [Line Amt.],
SH.[Currency] AS [Currency],
FROM [Sales Header] SH
JOIN [Sales Line] SL ON SL.[Document No_] = SH.[No_]
GROUP BY
SH.[No_],
SH.[Salesperson],
SH.[Order Date],
SH.[Customer No_],
SH.[Customer Name],
SH.[Country],
SH.[Currency],
SL.[Quantity],
SL.[Unit of Measure],
SL.[No_],
SL.[Description],
SH.[Document Type],
SL.[Unit Price]
HAVING
SH.[Document Type] = '0' OR SH.[Document Type] = '1' AND SL.[Quantity] > '0'
解决方案
要实现小计行,您需要在客户端进行多个查询或聚合。通过多个查询,您可以多次查询数据存储或将初始详细信息放在临时表中,然后获取摘要。下面是多次查询。在查询之间存在数据更改的轻微风险。
-- Line details
SELECT
CONVERT(VARCHAR(12), SH.[Order Date], 107) AS [Posting Date]
,SH.[Salesperson] AS [Sales Staff]
,SH.[No_] AS [Document No]
,SH.[Customer No_] AS [Cust. No.]
,SH.[Customer Name] AS [Customer Name]
,SH.[Country] AS [Country]
,CONVERT(DECIMAL(10, 0), SL.[Quantity]) AS [Qty.]
,SL.[Unit of Measure] AS [UOM]
,SL.[No_] AS [Product No.]
,SL.[Description] AS [Product Description]
,CONVERT(DECIMAL(10, 2), SL.[Unit Price]) AS [Unit Price]
,SUM(CONVERT(DECIMAL(10, 2), SL.[Line Amount])) AS [Line Amt.]
,SH.[Currency] AS [Currency]
,'Detail' LineType
FROM [Sales Header] SH
INNER JOIN [Sales Line] SL ON SL.[Document No_] = SH.[No_]
WHERE SH.[Document Type] = '0'
OR SH.[Document Type] = '1'
AND SL.[Quantity] > '0'
GROUP BY
SH.[Order Date]
,SH.[Salesperson]
,SH.[No_]
,SH.[Customer No_]
,SH.[Customer Name]
,SH.[Country]
,SL.[Quantity]
,SL.[Unit of Measure]
,SL.[No_]
,SL.[Description]
,SL.[Unit Price]
,SH.[Currency]
UNION ALL
-- Order Summary
SELECT [Posting Date]
, [Sales Staff]
, [Document No]
, [Cust. No.]
, [Customer Name]
, [Country]
, NULL AS [Qty.] -- not needed is sub total line
, NULL AS [UOM] -- not needed is sub total line
, NULL AS [Product No.] -- not needed is sub total line
, NULL AS [Product Description] -- not needed is sub total line
, NULL AS [Unit Price] -- not needed is sub total line
, SUM(CONVERT(DECIMAL(10, 2), SL.[Line Amount])) OVER (PARTITION BY SH.[No_]) AS [Line Amt.] -- TotalAmountByOrder
, [Currency]
,'Order' LineType
FROM
(
SELECT
CONVERT(VARCHAR(12), SH.[Order Date], 107) AS [Posting Date]
,SH.[Salesperson] AS [Sales Staff]
,SH.[No_] AS [Document No]
,SH.[Customer No_] AS [Cust. No.]
,SH.[Customer Name] AS [Customer Name]
,SH.[Country] AS [Country]
,CONVERT(DECIMAL(10, 0), SL.[Quantity]) AS [Qty.]
,SL.[Unit of Measure] AS [UOM]
,SL.[No_] AS [Product No.]
,SL.[Description] AS [Product Description]
,CONVERT(DECIMAL(10, 2), SL.[Unit Price]) AS [Unit Price]
,SUM(CONVERT(DECIMAL(10, 2), SL.[Line Amount])) AS [Line Amt.]
,SH.[Currency] AS [Currency]
FROM [Sales Header] SH
INNER JOIN [Sales Line] SL ON SL.[Document No_] = SH.[No_]
WHERE SH.[Document Type] = '0'
OR SH.[Document Type] = '1'
AND SL.[Quantity] > '0'
GROUP BY
SH.[Order Date]
,SH.[Salesperson]
,SH.[No_]
,SH.[Customer No_]
,SH.[Customer Name]
,SH.[Country]
,SL.[Quantity]
,SL.[Unit of Measure]
,SL.[No_]
,SL.[Description]
,SL.[Unit Price]
,SH.[Currency]
) T
UNION ALL
-- Grand total
SELECT NULL AS [Posting Date]
, NULL AS [Sales Staff]
, NULL AS [Document No]
, NULL AS [Cust. No.]
, NULL AS [Customer Name]
, NULL AS [Country]
, NULL AS [Qty.] -- not needed is total line
, NULL AS [UOM] -- not needed is total line
, NULL AS [Product No.] -- not needed is total line
, NULL AS [Product Description] -- not needed is total line
, NULL AS [Unit Price] -- not needed is total line
, SUM(CONVERT(DECIMAL(10, 2), SL.[Line Amount])) OVER (PARTITION BY 1) AS [Line Amt.] -- TotalAmountAllOrders
, NULL AS [Currency] -- not needed is total line
, 'All' LineType
FROM [Sales Header] SH
INNER JOIN [Sales Line] SL ON SL.[Document No_] = SH.[No_]
WHERE SH.[Document Type] = '0'
OR SH.[Document Type] = '1'
AND SL.[Quantity] > '0'
初步反应
很高兴看到示例数据或表结构。根据您所拥有的,我对您要达到的目标的最佳猜测如下。
SELECT
CONVERT(VARCHAR(12), SH.[Order Date], 107) AS [Posting Date]
,SH.[Salesperson] AS [Sales Staff]
,SH.[No_] AS [Document No]
,SH.[Customer No_] AS [Cust. No.]
,SH.[Customer Name] AS [Customer Name]
,SH.[Country] AS [Country]
,CONVERT(DECIMAL(10, 0), SL.[Quantity]) AS [Qty.]
,SL.[Unit of Measure] AS [UOM]
,SL.[No_] AS [Product No.]
,SL.[Description] AS [Product Description]
,CONVERT(DECIMAL(10, 2), SL.[Unit Price]) AS [Unit Price]
,SUM(CONVERT(DECIMAL(10, 2), SL.[Line Amount])) AS [Line Amt.]
,SH.[Currency] AS [Currency]
,SUM(CONVERT(DECIMAL(10, 2), SL.[Line Amount])) OVER (PARTITION BY SH.[No_]) TotalAmountByOrder
,SUM(CONVERT(DECIMAL(10, 2), SL.[Line Amount])) OVER (PARTITION BY SH.[Salesperson]) TotalAmountBySalesPerson
,SUM(CONVERT(DECIMAL(10, 2), SL.[Line Amount])) OVER (PARTITION BY SH.[Customer No_]) TotalAmountByCustomer
,SUM(CONVERT(DECIMAL(10, 2), SL.[Line Amount])) OVER (PARTITION BY 1) TotalAmounAllOrders
FROM [Sales Header] SH
INNER JOIN [Sales Line] SL ON SL.[Document No_] = SH.[No_]
WHERE SH.[Document Type] = '0'
OR SH.[Document Type] = '1'
AND SL.[Quantity] > '0'
GROUP BY
SH.[Order Date]
,SH.[Salesperson]
,SH.[No_]
,SH.[Customer No_]
,SH.[Customer Name]
,SH.[Country]
,SL.[Quantity]
,SL.[Unit of Measure]
,SL.[No_]
,SL.[Description]
,SL.[Unit Price]
,SH.[Currency]
尽管在这种情况下是正确的,但理想情况下属于 where 子句。将其移至 where 子句,我们不再需要它在分组中,并且我们不再需要在 group by 中包含 SH.[Document Type]。
重新排序您的组。这样做只是为了比较 select 语句中的所有列以确认没有遗漏
添加了一些聚合列。每个订单、每个销售人员、每个客户和总计的总和。您可以使用这些示例中的任何一个来计算出您需要的确切总数。
推荐阅读
- json - 我将一个 json 文件导入到 swagger-editor,它会自动将其转换为 yaml。我该如何防止这种情况?
- android - 使用流畅的动画更改标记大小
- java - 在 Spring 中模拟 @InjectMocks 的方法
- haskell - Haskell 中的可见类型应用:如何绑定类型
- javascript - 使用 Ajax 更新特定对象中单个字段的正确方法
- sql-server - SQL Server:如果列值不为空,则从两行中选择行
- qt - 如何从 Qt 中的另一个文件访问另一个对象中的一个对象的属性?
- typescript - 如何使用 Typescript 3.2.2 进行命令行编译?
- java - 未知错误:DevToolsActivePort 文件不存在
- spark-structured-streaming - 如何使用 Java Spark 结构化流 API 合并两个数据帧,而不添加索引并加入它们?