跨多个项目拆分货运

时间:2017-08-16 21:16:06

标签: sql sql-server sql-server-2008-r2

给出如下SQL查询

DECLARE @StartDate NVARCHAR(MAX) = '20170815'
DECLARE @FinishDate NVARCHAR(MAX) = '20170815'      

 SELECT 
  cid.ItemCode,
  cid.InvoiceCode,
  SUM(ROUND(cid.ExtPrice, 2)) AS 'TotalExGST'
  FROM CustomerInvoice ci
    JOIN CustomerInvoiceDetail cid 
      ON ci.InvoiceCode = cid.InvoiceCode
  WHERE ci.IsVoided = 0
  AND dbo.ConvertDate_C(ci.InvoiceDate) 
    BETWEEN @StartDate AND @FinishDate
  GROUP BY ci.invoicecode, ItemCode

UNION ALL

SELECT 
'Freight',
ci.InvoiceCode,
ci.Freight
FROM CustomerInvoice ci                         
  WHERE ci.IsVoided = 0
  AND dbo.ConvertDate_C(ci.InvoiceDate) BETWEEN @StartDate AND @FinishDate
GROUP BY ci.invoicecode, ci.Freight

返回这样的数据(为简单起见,只显示一张发票)

╔═════════════╦══════════════╦══════════════╗
║ Item Code   ║ Invoice Code ║ Total Ex GST ║
╠═════════════╬══════════════╬══════════════╣
║ Freight     ║ INV-255390   ║ 20.000000    ║
╠═════════════╬══════════════╬══════════════╣
║ ITEM-002605 ║ INV-255390   ║ 47.120000    ║
╠═════════════╬══════════════╬══════════════╣
║ ITEM-002679 ║ INV-255390   ║ 11.260000    ║
╠═════════════╬══════════════╬══════════════╣
║ ITEM-002687 ║ INV-255390   ║ 10.860000    ║
╠═════════════╬══════════════╬══════════════╣
║ ITEM-028905 ║ INV-255390   ║ 58.480000    ║
╚═════════════╩══════════════╩══════════════╝

如何获取每张发票上的订单项总数,并将运费金额按该总额平均分摊,然后将其与项目价格相加?

项目和价格位于CustomerInvoiceDetail表格上,而运费则位于CustomerInvoice表格上,这些可以在InvoiceCode列上加入。

预期输出看起来像,并按如下方式计算:

Number of items on invoice = 4
Freight cost = 20
Split Freight Cost = 20 / 4 = 5
Then add 5 to all the items, and thus remove freight row from the query.

╔═════════════╦═════════════╦════════════╗
║ ItemCode    ║ InvoiceCode ║ TotalExGST ║
╠═════════════╬═════════════╬════════════╣
║ ITEM-002605 ║ INV-255390  ║ 52.12      ║
╠═════════════╬═════════════╬════════════╣
║ ITEM-002679 ║ INV-255390  ║ 16.26      ║
╠═════════════╬═════════════╬════════════╣
║ ITEM-002687 ║ INV-255390  ║ 15.86      ║
╠═════════════╬═════════════╬════════════╣
║ ITEM-028905 ║ INV-255390  ║ 63.48      ║
╚═════════════╩═════════════╩════════════╝

2 个答案:

答案 0 :(得分:1)

我会将您的查询包装到CTE中以使其更具可读性。

CTE_InvoiceFreight每张发票一行包含运费金额。

CTE_InvoiceItems提供发票项目。

我与LEFT JOIN加入,以防有没有运费的发票。

COUNT(*) OVER (...)会计算每张发票中的项目数,而不会额外GROUP BY

取消评论最终SELECT中的列,以查看中间结果。

DECLARE @StartDate NVARCHAR(MAX) = '20170815'
DECLARE @FinishDate NVARCHAR(MAX) = '20170815'

WITH
CTE_InvoiceFreight
AS
(
    -- this query returns at most one row per InvoiceCode
    SELECT
        ci.InvoiceCode
        ,SUM(ci.Freight) AS TotalInvoiceFreight
    FROM
        CustomerInvoice AS ci
    WHERE
        ci.IsVoided = 0
        AND dbo.ConvertDate_C(ci.InvoiceDate) BETWEEN @StartDate AND @FinishDate
    GROUP BY
        ci.InvoiceCode
)
,CTE_InvoiceItems
AS
(
    SELECT
        cid.ItemCode
        ,cid.InvoiceCode
        ,SUM(ROUND(cid.ExtPrice, 2)) AS TotalExGST
    FROM
        CustomerInvoice AS ci
        INNER JOIN CustomerInvoiceDetail AS cid ON ci.InvoiceCode = cid.InvoiceCode
    WHERE
        ci.IsVoided = 0
        AND dbo.ConvertDate_C(ci.InvoiceDate) BETWEEN @StartDate AND @FinishDate
    GROUP BY
        cid.ItemCode
        ,cid.InvoiceCode
)
SELECT
    CTE_InvoiceItems.ItemCode
    ,CTE_InvoiceItems.InvoiceCode

--  ,CTE_InvoiceItems.TotalExGST
--  ,COUNT(*) OVER (PARTITION BY CTE_InvoiceItems.InvoiceCode) AS InvoiceItemsCount
--  ,ISNULL(CTE_InvoiceFreight.TotalInvoiceFreight, 0) AS TotalInvoiceFreight

    ,CTE_InvoiceItems.TotalExGST
    + ROUND(
        ISNULL(CTE_InvoiceFreight.TotalInvoiceFreight, 0) / 
        COUNT(*) OVER (PARTITION BY CTE_InvoiceItems.InvoiceCode)
    , 2) AS TotalWithFreightExGST
FROM
    CTE_InvoiceItems
    LEFT JOIN CTE_InvoiceFreight 
        ON CTE_InvoiceFreight.InvoiceCode = CTE_InvoiceItems.InvoiceCode
ORDER BY
    CTE_InvoiceItems.InvoiceCode
    ,CTE_InvoiceItems.ItemCode
;

答案 1 :(得分:0)

结束使用每张发票上的发票代码和项目数进行子查询。

然后我用它来计算拆分运费金额并将其添加到每个项目中。

SELECT 
  ci.InvoiceDate,
  ci.InvoiceCode, 
  cid.ItemCode, 
  SUM(ROUND(cid.ExtPrice, 2)) + SUM(ROUND((ci.Freight / ItemSum.NoOfItems),2)) + SUM(ROUND((ci.Other / ItemSum.NoOfItems),2)) AS 'TotalExGst', 

  FROM CustomerInvoiceDetail cid
  JOIN (
      SELECT ci.InvoiceCode, COUNT(*) AS 'NoOfItems' 
      FROM CustomerInvoiceDetail cid
          JOIN CustomerInvoice ci 
        ON cid.InvoiceCode = ci.InvoiceCode
          GROUP BY ci.InvoiceCode
  ) ItemSum 
  ON cid.InvoiceCode = ItemSum.InvoiceCode

  JOIN CustomerInvoice ci ON cid.InvoiceCode = ci.InvoiceCode
  WHERE ci.IsVoided = 0
  AND dbo.ConvertDate_C(ci.InvoiceDate) 
  BETWEEN @StartDate AND @FinishDate
  GROUP BY ci.InvoiceCode, cid.ItemCode, ci.InvoiceDate