SQL子查询-有更好的方法吗

标签 sql sql-server performance

这是一个SQL效率问题。

不久前,我必须编写一组查询来从 ERP 系统中提取数据。其中大多数都很简单,但其中一个导致了相当低效的查询,从那时起它就一直困扰着我,因为必须有更好的方法。

问题并不复杂。您有几行销售数据。每行都有数量、销售价格和销售人员代码以及其他信息。

佣金按阶梯式 float 比例支付。他们卖得越多,佣金就越高。步骤可能是 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 件商品时向他们提供特定产品的折扣。销售员卖得越多,收入就应该越高。

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

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

最佳答案

如果您使用支持公用表表达式的 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

如果您需要考虑到 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

关于SQL子查询-有更好的方法吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3081080/

相关文章:

java - 如何获得 jdbc 提交的解释分析?

sql - 当数组为空而没有动态sql时,Postgres sql返回所有

sql-server - 限制 SQL Server 中的 NVARCHAR 大小?

当前打卡员工的 SQL 列表

c - 将 int 数组快速转换为 fp 以进行音频处理

javascript - 使用attr()方法,将属性作为键值对象或直接传递时,哪种方法在jQuery中添加属性时执行最快?

mysql - SQL:如何查找查询返回的总数据大小(以字节为单位)?

mysql - SQL获取每个值的不同行数

sql-server - 如何在 SQL SERVER 中自动增加合并表不匹配大小写的列?

sql-server - T-sql : how to perform optimised Paging?