【问题标题】:Trouble creating SQL Query to update line item amounts创建 SQL 查询以更新行项目金额时遇到问题
【发布时间】:2012-02-16 00:57:08
【问题描述】:

我将在这个问题的开头加上免责声明,即创建我所谓的“复杂”查询并不是我的专长。大多数时候,有一种更简单的方法可以完成我想要完成的任务,所以如果下面的查询不符合标准,我深表歉意。

话虽如此,我有一个表格来跟踪供应商发票和供应商发票项目(以及供应商发票类型和供应商发票项目类型)。我们的簿记员想要一份简单显示的报告: 供应商 |位置 |发票号 |投资类型 |项目类型 |日期 |租金 |进货费 |运费 |行项目成本 |总计(订单项 + 费用)

大多数情况下,一张供应商发票是一行。但是,供应商发票可以有许多项目类型,因此会创建两行。没什么大不了的,除了费用(租金、补货、运输)附在供应商发票表上。因此,我首先创建了一个查询,检查临时表中是否有包含多行的 Invoices,取最后一行,然后将费用归零。这样只有一个订单项会收取费用。但是,我们的簿记员不喜欢这样。相反,她希望在订单项之间“分配”费用。

因此,如果供应商发票的运费为 25 美元,并且有两个行项目,那么每个行项目将为 12.50 美元。

在处理完查询后,我将最后一行更新为调整后的金额,但第 1+ 行将具有原始金额。

我将在此处发布我的整个查询(再次 - 很抱歉,这可能不是最好看的查询;但是,总是欢迎提出建议)

DROP TABLE #tVendorInvoiceReport
DROP TABLE #tSummary

SELECT  v.Name AS Vendor ,
    vii.Location ,
    vi.VendorInvNumber ,
    vit.Descr AS InvoiceType ,
    vii.VendorInvoiceItemType ,
    CONVERT(VARCHAR(10), vi.VendorInvDate, 120) VendorInvDate ,
    vi.RentalFee ,
    vi.RestockFee ,
    vi.ShippingFee ,
    SUM(vii.TotalUnitCost) TotalItemCost ,
    CONVERT(MONEY, 0) TotalInvoice  ,
    RowID = IDENTITY( INT,1,1)
INTO    #tVendorInvoiceReport
FROM    dbo.vVendorInvoiceItems AS vii
    JOIN dbo.VendorInvoices AS vi ON vii.VendorInvID = vi.VendorInvID
    JOIN dbo.Vendors AS v ON vi.VendorID = v.VendorID
    JOIN dbo.VendorInvoiceTypes AS vit ON vi.VendorInvTypeID = vit.VendorInvTypeID
WHERE   vi.VendorInvDate >= '2012-01-01'
    AND vi.VendorInvDate <= '2012-01-31'
GROUP BY v.Name ,
    vii.Location ,
    vi.VendorInvNumber ,
    vit.Descr ,
    vii.VendorInvoiceItemType ,
    CONVERT(VARCHAR(10), vi.VendorInvDate, 120) ,
    vi.RentalFee ,
    vi.RestockFee ,
    vi.ShippingFee
ORDER BY v.Name ,
    vii.Location ,
    vi.VendorInvNumber ,
    vit.Descr ,
    vii.VendorInvoiceItemType ,
    CONVERT(VARCHAR(10), vi.VendorInvDate, 120)


SELECT  VendorInvNumber ,
    COUNT(RowID) TotalLines ,
    MAX(RowID) LastLine
INTO    #tSummary
FROM    #tVendorInvoiceReport
GROUP BY VendorInvNumber

WHILE ( SELECT  COUNT(LastLine)
    FROM    #tSummary AS ts
    WHERE   TotalLines > 1
  ) > 0 
BEGIN
    DECLARE @LastLine INT
    DECLARE @NumItems INT

    SET @LastLine = ( SELECT    MAX(LastLine)
                      FROM      #tSummary AS ts
                      WHERE     TotalLines > 1
                    )

    SET @NumItems = ( SELECT    COUNT(VendorInvNumber)
                      FROM      #tVendorInvoiceReport
                      WHERE     VendorInvNumber IN (
                                SELECT  VendorInvNumber
                                FROM    #tSummary
                                WHERE   LastLine = @LastLine )
                    ) 

    UPDATE  #tVendorInvoiceReport
    SET     RentalFee = ( RentalFee / @NumItems ) ,
            RestockFee = ( RestockFee / @NumItems ) ,
            ShippingFee = ( ShippingFee / @NumItems )
    WHERE   RowID = @LastLine

    DELETE  FROM #tSummary
    WHERE   LastLine = @LastLine

    --PRINT @NumItems
END

UPDATE  #tVendorInvoiceReport
SET     TotalInvoice = ( TotalItemCost + RentalFee + RestockFee + ShippingFee )

SELECT  Vendor ,
    Location ,
    VendorInvNumber ,
    InvoiceType ,
    VendorInvoiceItemType ,
    VendorInvDate ,
    RentalFee ,
    RestockFee ,
    ShippingFee ,
    TotalItemCost ,
    TotalInvoice
FROM    #tVendorInvoiceReport AS tvir

我衷心感谢任何花时间阅读本文并试图为我指明正确方向的人。

谢谢, 安德鲁

PS - 我确实尝试从第一个更新中删除“WHERE RowID = @LastLine”,但这将第一行的运费更改为“0.0868”而不是 12.50 ($25/2)

【问题讨论】:

  • 请创建一个更简单的示例,显示表结构,以及更新前后的示例数据。
  • 如果没有发布示例,我不完全确定如何准确传达我需要的内容。我正要输入一些示例数据,但幸运的是 @jim31415 帮助了我。感谢您查看这篇文章!

标签: sql-server sql-server-2008 tsql


【解决方案1】:

如果我理解正确,您正在寻找一种方法,将发票运费等费用拆分为一个或多个发票项目。

我创建了一些示例发票和发票项目表,如下所示,并使用了 over(partition) clause 拆分每件商品的运费。

-- sample tables
declare @Invoice table (InvoiceID int, customerID int, Date datetime, ShippingFee float)
declare @InvoiceItem table (InvoiceItemID int identity, InvoiceID int, ItemDesc varchar(50), Quantity float, ItemPrice float)

-- Example 1
insert @Invoice values(1, 800, getdate(), 20);
insert @InvoiceItem values(1, 'Widget', 1, 10.00)
insert @InvoiceItem values(1, 'Wing Nut', 5, 2.00)
insert @InvoiceItem values(1, 'Doodad', 8, 0.50)
insert @InvoiceItem values(1, 'Thingy', 3, 1.00)

-- Example 2
insert @Invoice values(2, 815, getdate(), 15);
insert @InvoiceItem values(2, 'Green Stuff', 10, 1.00)
insert @InvoiceItem values(2, 'Blue Stuff', 10, 1.60)

-- Example 3
insert @Invoice values(3, 789, getdate(), 15);
insert @InvoiceItem values(3, 'Widget', 10, 1.60)

-- query
select 
    n.InvoiceID,
    n.InvoiceItemID,
    n.ItemDesc,
    n.Quantity,
    n.ItemPrice,
    ExtendedPrice = n.Quantity *    n.ItemPrice,
    Shipping = i.ShippingFee / count(n.InvoiceItemID) over(partition by n.InvoiceID)
from @InvoiceItem n
    join @Invoice i on i.InvoiceID = n.InvoiceID

输出:

    InvoiceID   InvoiceItemID   ItemDesc    Quantity    ItemPrice   ExtendedPrice   Shipping
    1           1               Widget      1           10          10                  5
    1           2               Wing Nut    5           2           10                  5
    1           3               Doodad      8           0.5         4                   5
    1           4               Thingy      3           1           3                   5

    2           5               Green Stuff 10          1           10                  7.5
    2           6               Blue Stuff  10          1.6         16                  7.5

    3           7               Widget      10          1.6         16                  15

【讨论】:

  • 您先生,是一位绅士和一位学者。我知道我的问题不是最清楚的,并且我没有定义表结构或数据集(我可能应该这样做),但是您是 Stack Overflow 只是一个令人难以置信的资源的众多原因之一。我在我的查询中实现了你的逻辑,它工作得很好。此外,你还教了我一个新功能(over & partition by)。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多