产品:
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'
,因此我知道哪个是哪个。希望这是有道理的。
规则:
答案 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。