0

我想在同一个查询中为不同的输入变量多次加入同一个表函数。但在我的情况下,这比使用表变量和分别从表函数中选择要慢得多。

我怎样才能避免表变量并且仍然有一个快速查询?

例如,我们有一个 SQL 查询,如

选择 P.ProjectName、A.Number、B.Number
来自项目 AS P
左加入 dbo.fn_ProjectNumber(@dateA) 作为 A
    ON P.ProjectID = A.ProjectID
左连接 dbo.fn_ProjectNumber(@dateB) AS B
    ON P.ProjectID = B.ProjectID

但它比从函数中分别选择到变量中然后再加入要慢得多,例如:

插入@tempA
选择 P.ProjectID、A.Number
来自项目 AS P
左加入 dbo.fn_ProjectNumber(@dateA) 作为 A
    ON P.ProjectID = A.ProjectID

插入@tempB
选择 P.ProjectID、B.Number
来自项目 AS P
左连接 dbo.fn_ProjectNumber(@dateB) AS B
    ON P.ProjectID = B.ProjectID

选择 P.ProjectName、A.Number、B.Number
来自项目 AS P
左加入 @tempA 作为 A
    ON P.ProjectID = A.ProjectID
左加入 @tempA 作为 B
    ON P.ProjectID = B.ProjectID

这可能是什么原因?有没有办法可以快速查询并避免表变量?


更多细节:

这只是一个类似于我正在做的例子,但该函数fn_ProjectNumber(@date datetime)将包含四个表之间的连接之类的东西......


    
4

4 回答 4

1

尝试修复连接,您在第二个 LEFT JOIN 中引用了错误的别名:

原来的:

SELECT P.ProjectName, A.Number, B.Number
FROM Project AS P
LEFT JOIN dbo.fn_ProjectNumber(@dateA) AS A
    ON P.ProjectID = A.ProjectID
LEFT JOIN dbo.fn_ProjectNumber(@dateB) AS B
    ON P.ProjectID = A.ProjectID

固定的:

SELECT P.ProjectName, A.Number, B.Number
FROM Project AS P
LEFT JOIN dbo.fn_ProjectNumber(@dateA) AS A
    ON P.ProjectID = A.ProjectID
LEFT JOIN dbo.fn_ProjectNumber(@dateB) AS B
    ON P.ProjectID = B.ProjectID --<<<<<
于 2009-09-29T13:36:24.410 回答
1

您有什么特别的原因要避免使用表变量吗?它们可以是一种很好的优化技术,并且不会留下任何临时对象来清理。

无论如何,如果您不想那样做,您可以随时尝试

SELECT
    P.ProjectID, A.Number, B.Number
FROM
    Project AS P
        LEFT JOIN
            (SELECT P.ProjectID, A.Number
            FROM Project AS P
            LEFT JOIN dbo.fn_ProjectNumber(@dateA) AS A
               ON P.ProjectID = A.ProjectID
            ) AS A
                ON P.ProjectID = A.ProjectID
        LEFT JOIN
            (SELECT P.ProjectID, B.Number
            FROM Project AS P
            LEFT JOIN dbo.fn_ProjectNumber(@dateB) AS B
                ON P.ProjectID = B.ProjectID
            ) AS B
                ON P.ProjectID = B.ProjectID
于 2009-09-29T13:37:10.183 回答
1

连接很慢,因为在您的示例查询中,您为表 Project 中的每一行调用每个函数一次。使用临时表更快,因为您只调用该函数一次。

避免临时表的一种方法是使用 CTE(通用表表达式——它们不仅用于递归——在 SQL 2005 及更高版本中可用。)。一般语法类似于:

WITH cteTempName (<list of columns>)
 as (<your table function call>)
 SELECT <your query here, with "cteTempName" appearing as just another table to select from>
于 2009-09-29T14:02:48.900 回答
0

也许连接速度较慢,因为您没有定义连接在一起的表之间的关系?我对 SQL Server 中的查询性能了解不多,但定义关系将提高连接的性能。

于 2009-09-29T13:35:33.557 回答