【问题标题】:Split freight across multiple items跨多个项目拆分运费
【发布时间】:2017-08-17 12:07:22
【问题描述】:

给定一个 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      ║
╚═════════════╩═════════════╩════════════╝

【问题讨论】:

  • 预期的输出是什么样子的
  • 查看更新的问题 ;)

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


【解决方案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
;

【讨论】:

    【解决方案2】:

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

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

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-09
      • 2011-05-02
      • 2012-05-17
      • 1970-01-01
      • 2011-07-02
      • 2015-08-04
      • 2014-05-01
      相关资源
      最近更新 更多