0

我必须进行查询以获取上个月的总成本并与当月进行比较以计算百分比差异。

这是脚本:

create table #calc 
(
InvoiceDate Date,
TotalCost decimal (12,2)
)

insert into #calc values ('2013-07-01', 9470.36)
insert into #calc values ('2013-08-01', 11393.81)

这是查询:

select InvoiceDate, 
       TotalCost, 
       PrevTotalCost, 
       (CASE WHEN (PrevTotalCost = 0)
             THEN 0
             ELSE (((TotalCost - PrevTotalCost) / PrevTotalCost) * 100.0) 
        END) AS PercentageDifference
from (
select a.InvoiceDate, a.TotalCost, 
       isnull((select b.TotalCost 
          from #calc b 
         where InvoiceDate = (select MAX(InvoiceDate) 
                                from #calc c 
                               where c.InvoiceDate < a.InvoiceDate)), 0) as PrevTotalCost
  from #calc a) subq

有没有更有效的方法来完成上个月的 cgetting?

4

2 回答 2

0

在不使用索引的情况下,使用排名函数给排序带来比表扫描更多的负担似乎是最快的。下面的查询在一秒钟内处理了 6575 条记录:

SELECT
    Main.InvoiceDate,
    Main.TotalCost,
    PreviousTotalCost=Previous.TotalCost,
    PercentageDifference=
        CASE WHEN COALESCE(Previous.TotalCost,0) = 0 THEN 0
             ELSE (((Main.TotalCost - Previous.TotalCost) / Previous.TotalCost) * 100.00) 
        END
FROM
(
    SELECT 
        InvoiceDate,
        TotalCost,
        OrderInGroup=ROW_NUMBER() OVER (ORDER BY InvoiceDate DESC)      
    FROM
        Test
)AS Main
LEFT OUTER JOIN
(
    SELECT
        InvoiceDate,
        TotalCost,
        OrderInGroup=ROW_NUMBER() OVER (ORDER BY InvoiceDate DESC)
    FROM
        Test
)AS Previous ON Previous.OrderInGroup=Main.OrderInGroup+1

在选择子查询中获取上一个发票成本时使用嵌套循环证明最慢 - 30 秒内 6575 行。

SELECT
    X.InvoiceDate,
    X.TotalCost,
    X.PreviousTotalCost,
    PercentageDifference=
        CASE WHEN COALESCE(X.PreviousTotalCost,0) = 0 THEN 0
             ELSE (((X.TotalCost - X.PreviousTotalCost) / X.PreviousTotalCost) * 100.00) 
        END

FROM
(
    SELECT 
        InvoiceDate,
        TotalCost,
        PreviousTotalCost=(SELECT TotalCost FROM Test WHERE InvoiceDate=(SELECT MAX(InvoiceDate) FROM Test WHERE InvoiceDate<Main.InvoiceDate))     
    FROM
        Test AS Main
)AS X

您的查询在 20 秒内处理了 6575 条记录,其中最大的成本来自内部连接的嵌套循环

select InvoiceDate, 
       TotalCost, 
       PrevTotalCost, 
       (CASE WHEN (PrevTotalCost = 0)
             THEN 0
             ELSE (((TotalCost - PrevTotalCost) / PrevTotalCost) * 100.0) 
        END) AS PercentageDifference
from (
select a.InvoiceDate, a.TotalCost, 
       isnull((select b.TotalCost 
          from Test b 
         where InvoiceDate = (select MAX(InvoiceDate) 
                                from #calc c 
                               where c.InvoiceDate < a.InvoiceDate)), 0) as PrevTotalCost
  from Test a) subq

除非您需要使用临时表,否则使用索引将是一大优势。

希望这可以帮助 :)

于 2013-09-10T18:12:58.190 回答
0
SELECT 
    `current`.`InvoiceDate`,
    `current`.`TotalCost`,
    `prev`.`TotalCost` AS `PrevTotalCost`,
    (`current`.`TotalCost` - `prev`.`TotalCost`) AS `CostDifference`
FROM dates `current`
LEFT JOIN
    dates `prev`
    ON `prev`.`InvoiceDate` <= DATE_FORMAT(`current`.`InvoiceDate` - INTERVAL 1 MONTH, '%Y-%m-01');

我得到的结果截图:http: //cl.ly/image/0b3z2x1f2H1n

我想这可能是你正在寻找的。

编辑:我在 MySQL 中编写了这个查询,因此您可能需要为您的服务器更改一些小的语法内容。

于 2013-09-10T17:38:28.707 回答