有没有办法在子查询中获取分层有效负载数据?

时间:2017-08-23 18:17:24

标签: sql sql-server-2008 tsql

产品

ItemId   ItemName   ParentId    payload
----------------------------------------
    1    Food       null        payload1
    2    Drinks     null        payload2
    3    Other      null        payload3
    4    Fruits       1         payload4
    5    Vegetables   1         payload5
    6    Carrots      3         payload6
    7    Carrots      5         payload7

客户订单

CustId   ParentItemName   ItemName
----------------------------------
  1      Food             Carrots

问题:

select *, (???) from CustomerOrders

??? =有没有办法在子查询中获取'payload7'?请注意'Carrots'payload6的相同值,但我已获得父项'food',因此我知道哪个是哪个。希望这是有道理的。

规则:

  1. 加入不可用。
  2. 层次结构3-deep max
  3. 必须在子查询中发生

1 个答案:

答案 0 :(得分:2)

这里需要的是递归CTE。这是一个通过UNION引回自身的CTE。你给它一个起点(就像所有具有NULL父项的产品)作为种子,然后在UNION之后你引用回CTE并将它连接回表。然后它将迭代直到连接失败。

WITH recCTE AS
(
    --recursive seed (starting point of recursive query)
    SELECT
        ItemId,
        ItemId as RootParentId, --capture this starting point
        payload,
        0 as depth, --capture how deep we go into the hierarchy
        CAST(itemid AS VARCHAR(20)) as path --capture the path from the parent all the way down
    FROM products
    WHERE parentID IS NULL --Start at the top of the hierarchy

    --recursive term (the part executed over and over again)
    UNION ALL
    SELECT
        products.ItemId,
        recCTE.RootParentId,
        products.payload,
        depth + 1 as depth,
        CAST(recCTE.ItemId AS VARCHAR(20)) + '>' + CAST(products.ItemId AS VARCHAR(20))     
    FROM recCTE --refers to itself
        INNER JOIN products on reccte.ItemId = products.ParentID
    WHERE depth < 10 --just in case we get into a loop
)

--Now we can select from the results:
SELECT payload FROM recCTE where ItemID = 7 and RootPArentID = 1 --carrots and food;

这里我只从Products表中捕获了id,但你也可以添加你的ItemNames。一旦你的头脑缠绕它,这是一种非常有用的查询类型。

如果您将其合并到一个更大的查询中,那么它看起来像是:

WITH recCTE AS
(
    --recursive seed (starting point of recursive query)
    SELECT
        ItemId,
        ItemId as RootParentId --capture this starting point,
        payload,
        0 as depth, --capture how deep we go into the hierarchy
        CAST(itemid AS VARCHAR(20)) as path --capture the path from the parent all the way down
    FROM products
    WHERE parentID IS NULL --Start at the top of the hierarchy

    --recursive term (the part executed over and over again)
    UNION ALL
    SELECT
        products.ItemId,
        recCTE.RootParentId,
        products.payload,
        depth + 1 as depth,
        recCTE.ItemId + '>' + products.ItemId       
    FROM recCTE --refers to itself
        INNER JOIN products on reccte.ItemId = products.ParentID
    WHERE depth < 10 --just in case we get into a loop
)

SELECT sometable.somefield, subquery.payload
FROM sometable
    INNER JOIN recCTE as subquery ON sometable.productid = subquery.itemid and sometable.parentid = subquery.RootParentID;

所以CTE只是挂在顶部,变得像'&#34;子查询&#34;这真是一个CTE。