SQL子查询 - 有更好的方法

时间:2010-06-20 21:53:48

标签: sql sql-server performance

这是一个SQL效率问题。

前段时间我不得不编写一系列查询来从ERP系统中提取数据。其中大部分都很简单,但其中一个导致了一个相当低效的查询,并且一直困扰着我,因为必须有更好的方法。

问题并不复杂。您有一系列销售数据。在每一行中,您都有数量,销售价格和销售员代码以及其他信息。

佣金是基于阶梯式滑动比例支付的。他们卖的越多,佣金越多。步数可能是1000,10000,10000 $等等。现实世界的问题更复杂,但基本上就是这样。

我发现这样做的唯一方法就是做这样的事情(显然不是真正的查询)

select qty, price, salesman,
  (select top 1 percentage from comissions 
    where comisiones.salesman = saleslines.salesman 
    and saleslines.qty > comisiones.qty
    order by comissiones.qty desc
  ) percentage
from saleslines 

这导致了正确的佣金,但是非常沉重。

有更好的方法吗?我不是在找人重写我的sql,更多的是“看看foobar查询”,我可以从那里接受它。

可以为不同的销售人员,文章和客户甚至销售日期指定现实生活佣金结构。它也会不时变化,所以一切都必须由表中的数据驱动...即我不能在sql中放置固定范围。当前查询返回大约3-400000行,大约需要20-30秒。幸运的是它只用了一个月,但缓慢有点让我烦恼。

这是在mssql上。

伊恩

修改

我应该从一开始就给出一个更复杂的例子。我现在意识到,我最初的例子是缺少复杂性的一些基本要素,向所有人道歉。

这可能更好地捕捉它

select client-code, product, product-family, qty, price, discount, salesman,
    (select top 1 percentage from comissions 
        where comisiones.salesman = saleslines.salesman 
        and saleslines.qty > comisiones.qty
        and [
           a collection of conditions which may or may not apply:
           Exclude rows if the salesman has offered discounts above max discounts
                which appear in each row in the commissions table
           There may be a special scale for the product family
           There may be a special scale for the product
           There may be a special scale for the client

           A few more cases
            ]
        order by [
            The user can control the order though a table 
            which can prioritize by client, family or product
            It normally goes from most to least specific.
            ]
      ) percentage
    from saleslines 

不用说真正的查询不容易理解。只是为了让生活更有趣,它的命名是多语言。

因此,对于每一行销售线,佣金可能会有所不同。

这可能听起来过于复杂,但如果你想到如何支付佣金就有意义了。您不希望以高折扣价格向某人付款,如果他们购买X单位,您也希望能够为特定客户提供特定产品的折扣。如果他们卖得更多,推销员应该赚更多。

在上述所有内容中,我不包括日期限制特别优惠。

我认为分区可能是解决方案,但我需要更深入地探讨这个问题,因为我对分区一无所知。它给了我一些想法。

2 个答案:

答案 0 :(得分:3)

如果您使用的是支持公用表表达式(如SQL Server 2005及更高版本)的SQL Server版本,则可以采用更有效的解决方案:

With RankedCommissions As
    (
    Select SL.qty, SL.price, SL.salesman, C.percentage
        , Row_Number() Over ( Partition By SL.salesman Order By C.Qty Desc ) As CommissionRank
    From SalesLines As SL
        Join Commissions As C
            On SL.salesman = C.salesman
                 And SL.qty > C.qty
    )
Select qtr, price, salesman, percentage
From RankedCommissions
Where CommissionRank = 1

如果您需要考虑SalesLine.Qty>的给定销售员没有佣金值的可能性。 Commission.Qty,然后你可以做类似的事情:

With RankedCommissions As
    (
    Select SL.qty, SL.price, SL.salesman, C.percentage
        , Row_Number() Over ( Partition By SL.salesman Order By C.Qty Desc ) As CommissionRank
    From SalesLines As SL
        Join Commissions As C
            On SL.salesman = C.salesman
                And SL.qty > C.qty
    )
Select SL.qtr, SL.price, SL.salesman, RC.percentage
From SalesLines As SL
    Left Join RankedCommissions As RC
        On RC.salesman = SL.salesman
            And RC.CommissionRank = 1

答案 1 :(得分:0)

select 
     qty, price, salesman, 
     max(percentage)
from saleslines 
     inner join comissions on commisions.salesman = saleslines.salesman and 
          saleslines.qty > comissions.qty
group by 
     qty, price, salesman