【问题标题】:How to use function returned value in the same where clause of a query?如何在查询的同一个where子句中使用函数返回值?
【发布时间】:2021-07-08 15:45:41
【问题描述】:

我有如下表格:

Employees : EmployeeId, EmpName , DepartmentId

Transaction: TransactionId, EmployeeId

查询:

select distinct e.EmployeeId, e.EmpName, d.DepartmentId
    ,dbo.GetEmployeeCommissionByTransactionId(t.id) Commission
from Employees e
inner join Department d on e.DepartmentId = d.Id
left join [Transaction] t on t.EmployeeId = e.Id
where d.DepartmentId in (@departmentIds) 
--other filters
group by e.EmployeeId, e.EmpName, d.DepartmentId;

我还有 2 个过滤器,如下所示:

  • 最低佣金
  • 最大佣金

此最小和最大佣金将根据函数“dbo.GetEmployeeCommissionByTransactionId(t.id)”返回的值过滤数据。

现在,我知道我可以像这样将整个查询包装在 select 语句中:

select * from (My Query) as x
where x.Commission >=@minCommission
and x.Commission <=@maxCommission

但我怀疑这是否会产生正确的结果,或者这是否也有效。我只希望我的所有过滤器在同一个查询中协同工作以产生正确的结果。

难道不能在同一个where子句中使用函数返回值吗?

【问题讨论】:

  • 你是如何声明@departmentIds的?通常不能在 in 子句中使用变量,除非它是一个标量值,在这种情况下,这将产生与等于表达式相同的结果。如果它是一个表变量,那么你应该加入它而不是使用in 子句。
  • 用户定义的函数通常会影响性能。在这种情况下,使用子查询绝对不会让事情变得更糟,所以您不妨采用这种方法。
  • @GordonLinoff 其实 GetEmployeeCommissionByTransactionId 函数内部有很多逻辑来根据 Transaction Id 计算和返回佣金。
  • 如果您可以将该标量函数转换为内联表值函数会更好,但如果您不能这样做 - 那么您可以使用 CROSS APPLY 来执行该函数并返回该值。然后,您可以在 where 子句中使用该返回的列值。
  • @Jeff 你能告诉我如何使用外部应用,然后在 where 子句中返回列值吗?您介意发布答案吗

标签: sql sql-server tsql


【解决方案1】:

这里只是一个大纲:

Select ...
  From yourTable     t
 Cross Apply (Select Commission = dbo.YourFunction(t.id)) As y
 Where y.Commission >= @minCommission
   And y.Commission <  @maxCommission;

由于您正在过滤函数的返回值 - 外部应用是无用的。

如果你可以将函数重写为内联表值函数,你可以这样做:

Select ...
  From yourTable   t
 Cross Apply dbo.yourFunction(t.id)  y
 Where y.Commission >= @minCommission
   And y.Commission <  @maxCommission;

内联表值函数的性能比使用标量函数要好得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多