如何使用多列SQL获取小计?

时间:2019-04-08 21:41:45

标签: sql sql-server

希望生成有关销售订单和销售报价的报告,该报告将汇总和汇总以给出每个报价和订单的小计。

对于组合在一起的“文档编号”(订单/报价),其总“行金额”。

也很高兴能获得总计,但不是100%必需。

我尝试使用ROLLUP来生成此文件,但没有成功。

Click here for sample data and desired result

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'

1 个答案:

答案 0 :(得分: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]
  1. 尽管在这种情况下正确,但理想情况下属于where子句。将其移至where子句后,我们不再需要在分组中,也不再需要在group by中包含SH。[Document Type]。

  2. 对您的群组进行了重新排序。只是为了比较select语句中的所有列以确认没有丢失

  3. 添加了一些聚合列。每个订单,每个销售人员,每个客户和总计的总和。您可以使用任何这些示例来找出所需的确切总数。