尝试用JOIN替换Cross Apply

时间:2019-07-30 21:01:24

标签: sql sql-server-2017

我们已经建立了一个表ProductHierarchy。行数将保持不变。它具有简单的父/子产品层次结构数据。

我们还有一个表值函数,该函数接受一个ProductHierarchyId,然后返回该ID的IsDescendantOf为true的所有行。或者换句话说,它返回该行及其所有祖先。

问题在于,使用此表值函数,我们必须将其与CROSS APPLY一起使用,这严重降低了查询速度。

我的想法是创建第二个永久表(或相关查询中的临时表/表变量),该表具有已经存在的表值函数的所有可能结果。然后JOIN到该表,而不使用CROSS APPLY。在此表中,我们将添加一个名为QueryID之类的列。因此,而不是

CROSS APPLY dbo.GetProductLevels(P.ProductHierarchyId)

我们可以使用

LEFT JOIN FutureTable ft ON ft.QueryId = P.ProductHierarchyId

我正在努力创建该表的查询。这就是我到目前为止所拥有的...

SELECT
    *
    , 1 AS QueryId
FROM 
    dbo.ProductHierarchy
WHERE 
    (SELECT ProductHierarchyNode FROM dbo.ProductHierarchy WHERE ProductHierarchyId = 1).IsDescendantOf(ProductHierarchyNode) = 1 

好,因此对于ProductHierarchyId = 1的记录非常有用。但是接下来,我需要对ProductHierarchyId = 2重复一下。

SELECT
    *
    , 2 AS QueryId
FROM 
    dbo.ProductHierarchy
WHERE 
    (SELECT ProductHierarchyNode FROM dbo.ProductHierarchy WHERE ProductHierarchyId = 2).IsDescendantOf(ProductHierarchyNode) = 1 

然后循环3次,再循环4次,直到最后一个ID,每次在循环内执行UNION,这很可怕。

我知道有一种方法可以在一个查询中完成所有操作。类似于递归CTE。但是我的大脑没有到达那里。

1 个答案:

答案 0 :(得分:1)

你不只是这样做吗?

SELECT . . .    -- the columns you want
INTO . . .      -- where you want them
FROM dbo.ProductHierarchy ph CROSS APPLY
     dbo.GetProductLevels(P.ProductHierarchyId);