Ian*_*Ian 6 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
Run Code Online (Sandbox Code Playgroud)
这导致了正确的佣金,但是非常沉重.
有没有更好的方法呢?我不是在找人重写我的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
Run Code Online (Sandbox Code Playgroud)
不用说真正的查询不容易理解.只是为了让生活更有趣,它的命名是多语言.
因此,对于每一行销售线,佣金可以是不同的.
这可能听起来过于复杂,但如果你想到如何支付佣金,这是有道理的.您不希望以高折扣价格向某人付款,如果他们购买X单位,您也希望能够为特定客户提供特定产品的折扣.如果他们卖得更多,推销员应该赚更多钱.
在上述所有内容中,我不包括日期限制特别优惠.
我认为分区可能是解决方案,但我需要更深入地探讨这个问题,因为我对分区一无所知.它给了我一些想法.
如果您使用支持公用表表达式的 SQL Server 版本(例如 SQL Server 2005 及更高版本),则更有效的解决方案可能是:
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
Run Code Online (Sandbox Code Playgroud)
如果您需要考虑到 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
Run Code Online (Sandbox Code Playgroud)