sql优化-对联接查询中的每个不同id只执行一次函数

a7qyws3x  于 2021-07-24  发布在  Java
关注(0)|答案(4)|浏览(247)

我是一个完整的堆栈开发人员,对sql知之甚少。
考虑此代码->
(我把我的大问题简化为这一点,以明确我的疑问)

SELECT get_lowest_due_date(f.fileId)
    FROM File f
    JOIN Order o 
     ON o.fileId =  f.fileId

    File

    fileId     fileName
    --------------------
    1            file1
    2            file2

    Order

    orderId     orderName      fileId
    ----------------------------------
    1            order1           1
    2            order2           1
    3            order3           2

我相信 get_lowest_due_date() 正在为所有人执行死刑 fileId 联接查询返回的值(甚至是重复的)。
我是否可以让函数只对 fileId ? 我正在尝试优化查询。

g0czyy6m

g0czyy6m1#

您可以尝试:

SELECT get_lowest_due_date(a.fileId)
FROM (SELECT f.fileId 
      FROM File f
      JOIN Order o 
      ON o.fileId =  f.fileId
      GROUP BY f.fileId) a

内部查询返回唯一的fileid

bcs8qyzn

bcs8qyzn2#

sql存储函数(或存储过程)可以是确定性的。这意味着您的函数的结果只依赖于它的输入值,而不依赖于其他东西。例如, GETDATE() 是不确定的,而且 SQRT((x * x) + (y * y)) 是。
当一个函数是确定性的时,服务器优化器避免为相同的值多次调用该函数。如果函数不是确定性的,那么服务器优化器通常没有这种自由。
如果您的函数包含sql,那么明智的做法是将查询重构为联接或类似结构,将函数的sql直接放入查询中。这将允许mysql优化器以最好的方式合并其操作。
无论如何,您的示例会为中的每个值调用您的函数 File.fileId . 通过使用类似这样的嵌套查询,可以强制它只处理不同的值。

SELECT get_lowest_due_date(fileId)
   FROM (
           SELECT DISTINCT f.fileId
             FROM File f
            JOIN Order o 
                 ON o.fileId =  f.fileId
        ) f
bwntbbo3

bwntbbo33#

从问题的上下文来看,可能还有其他列,因此仅返回不同的文件ID不是一个选项。
例如,可以在上的子查询中调用函数 File :

SELECT f.*
FROM (SELECT f.*, get_lowest_due_date(f.fileId) as lowest_due_date
      FROM File f
     ) f JOIN
     Order o 
     ON o.fileId =  f.fileId;

您还可以使用其他技巧,例如:

select fo.*,
       max(first_lowest_due_date) over (partition by fileid) as lowest_due_date
from (select . . .,
             (case when row_number() over (partition by fileid order by orderid) = 1
                   then get_lowest_due_date(f.fileId) 
              end) as first_lowest_due_date
      from file f join
           orders o
           on o.fileid = f.fileid
     ) fo;

也就是说,我怀疑您认为用户定义函数是个好主意。sql不是一种编程语言,而且——唉——用户定义函数的性能非常糟糕。如果可能的话,我建议取消这个函数,也许使用视图或表值的内嵌函数。

cidc1ykv

cidc1ykv4#

对于select语句返回的每一行,标量函数都会被调用,而yes标量函数的性能不好。
可以将此标量函数转换为内联表值函数(因此表返回一个表而不是标量值),并使用交叉应用或外部应用来调用该函数。
功能定义:

CREATE FUNCTION dbo.get_lowest_due_date (@fileId INT)
RETURNS TABLE 
AS
RETURN 
(
  /* or whatever your logic is */
 SELECT Value from SomeTable WHERE fileId = @fileId
);

您的新查询:

SELECT *
    FROM File f
    JOIN Order o 
     ON o.fileId =  f.fileId
    CROSS APPLY  get_lowest_due_date(f.fileId)

相关问题