【问题标题】:Adding a SUM statement increases run time way too much, is there a better method?添加 SUM 语句会增加运行时间太多,有更好的方法吗?
【发布时间】:2020-10-07 22:23:50
【问题描述】:

我有一张包含发票付款的表格,可以是部分付款,也可以是全部付款。我将此计算字段与发票的总金额进行比较。我在查询中有两次,一次在 Select 语句中,一次在 Where 子句中。即使我删除了一个,所以它只在 Where 或 Select 中,运行也需要一个多小时。如果我完全删除 SUM,则需要 10 秒才能运行。

有没有更好的方法来获得总和?我应该使用索引视图吗?临时表?请注意,发票编号仅对供应商是唯一的,通常不是唯一的。最初的 FROM 是一个视图,如果这有区别的话。

select distinct
transdate,
invoicedate,
PAY.OrderAccount,
v.VendorName, 
invoiceamountmst,
(select sum(PAY1.settleamountcur) from [VIEW_INVOICE_PAYMENT] PAY1 where PAY.INVOICEID=PAY1.INVOICEID and PAY.OrderAccount=PAY1.OrderAccount) as "InvoiceSUM",
settleamountcur,
Currencycodeinvoice,
PAY.Description,
Voucher
from VIEW_INVOICE_PAYMENT PAY
inner join INVOICE on INVOICE_DOC_NO =invoiceid
JOIN VENDOR V on PAY.OrderAccount=v.VendorAccount
where TRANSDATE is not null
and (select sum(PAY1.settleamountcur) from [VIEW_INVOICE_PAYMENT] PAY1 where PAY.INVOICEID=PAY1.INVOICEID and PAY.OrderAccount=PAY1.OrderAccount)=total_cost_on_invoice

【问题讨论】:

    标签: sql sum


    【解决方案1】:

    在这个答案中,当我提到“那个选择”时,我指的是中间的子查询select sum(pay1.settlamountcur) ...

    请注意,“那个选择”中的别名看起来有点奇怪,例如 select sum(PAY1.settleamountcur) from [VIEW_INVOICE_PAYMENT] AX1。 PAY1 别名从何而来?我可能错过了什么。如果这是您的代码中的错字,则可能是在做坏事(如果它甚至可以运行)。但是,假设不是……

    对于您更广泛的问题,我相信它将为您的整个表返回的每一行运行一次该 select 语句。实际上,它可能会更频繁地执行此操作,具体取决于它何时在执行计划中进行过滤。

    注意我在这个答案中假设 SQL Server - 但它也应该适用于其他数据库。

    几个选项

    1. 不要引用视图,而是将表带入当前查询并修改查询
    2. 尝试从子查询中删除聚合,而是在整个数据集等上执行此操作,例如,GROUP BY 相关字段,跨相关字段求和。这可以与选项 1 结合使用。
    3. 将子查询作为 CTE 或 FROM 组件中的子查询。这可能使其将其用作单个表,而不是多次运行(或者可能不会)
    4. (有时我首选大型表)首先将视图中的相关数据放入临时表中,例如,
    SELECT INVOICEId, OrderAccount, SUM(settleamountcur) AS total_settleamountcur
        INTO #Temp
        FROM [VIEW_INVOICE_PAYMENT] 
        GROUP BY INVOICEId, OrderAccount
    
    -- Add any where/having clauses you can to filter
    -- Consider creating temp table first with primary key, making joins easier for SQL Server
    

    然后使用 #Temp 表代替 select 子查询。

    【讨论】:

    • 首先,感谢您的回复。你是对的,我在这里发布时概括了查询并忘记更新别名。现在编辑(AX1 更改为 PAY1)。另外,是的 SQL 服务器。
    • 对于第 2 点,我不确定您的意思,也许我理解错了。需要子查询中的 where 子句(据我所知)以确保我获取单个发票/供应商组合的总和。如果没有 where 子句,我只会得到所有付款的总和,重复每一行。
    • 我会根据你的建议来看看临时表。我对它们不太满意,但希望它能加快速度。尽管如果您删除 where 子句,它将获取整个表 VIEW_INVOICE_PAYMENT 的总和,而不是每张发票。所以我仍然担心填充临时表需要很长时间。会发现
    • 更新...我在没有任何 SUM 语句的情况下在临时表中进行了查询(必须添加 invoiceID 列,以便稍后可以进行主查询)。然后我像原来一样添加了 sum 语句,用临时表替换了子表。它在几秒钟内运行。所以这绝对是要走的路!所以我会做一个我猜的 SP,它创建表然后运行这个查询:'select (select sum(PAY.settleamountcur) from #MXP_AX_TEMP PAY where TEMP.INVOICEID=PAY.INVOICEID and TEMP.OrderAccount=PAY.OrderAccount)作为“InvoiceSUM”,* 来自 #MXP_AX_TEMP TEMP'
    • 优秀。我正在研究选项 2 等的示例,并且在理解分组和您正在尝试做的事情的含义时遇到了问题。但如果你有好的解决方案,我就不需要了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    相关资源
    最近更新 更多