Ed *_*d W 10 sql t-sql sql-server recursion
我有一个父/子关系表和一个引用自己的日期创建列.我想显示每个父记录以及节点上最近的"活动"所排序的所有后代.因此,如果很久以前创建的第1行有一个新的子项添加到其中(或者例如将一个新子项添加到其子项中),那么我希望它位于结果的顶部.
我目前无法正常工作.
我的表结构如下:
CREATE TABLE [dbo].[Orders](
[OrderId] [int] NOT NULL,
[Orders_OrderId] [int] NULL,
[DateOrdered] datetime)
Run Code Online (Sandbox Code Playgroud)
我编写了以下SQL来提取信息:
WITH allOrders AS
(SELECT po.orderid, po.Orders_OrderId, po.DateOrdered, 0 as distance,
row_number() over (order by DateOrdered desc) as RN1
FROM orders po WHERE po.Orders_OrderId is null
UNION ALL
SELECT b2.orderid ,b2.Orders_OrderId, b2.DateOrdered, c.distance + 1,
c.RN1
FROM orders b2
INNER JOIN allOrders c
ON b2.Orders_OrderId = c.orderid
)
SELECT * from allOrders
where RN1 between 0 and 2
order by rn1 asc, distance asc
Run Code Online (Sandbox Code Playgroud)
有什么方法可以"聚合"递归选择的结果,这样我就可以选择整个"父"节点的最大日期?
SQLFiddle演示:http://sqlfiddle.com/#!3/ca6cb/11 (记录号1应该是第一个,因为它有一个最近更新的子)
更新 感谢@twrowsell的建议我有以下查询,它确实有效,但看起来非常笨重,并且有一些性能问题,我觉得我不应该有3个CTE来实现这一点.有没有什么方法可以在保留"行号"的同时进行压缩(因为这是用于分页的用户显示)?
WITH allOrders AS
(SELECT po.orderid, po.Orders_OrderId, 0 as distance, po.DateOrdered, po.orderid as [rootId]
FROM orders po WHERE po.Orders_OrderId is null
UNION ALL
SELECT b2.orderid ,b2.Orders_OrderId, c.distance + 1, b2.DateOrdered, c.[rootId]
FROM orders b2
INNER JOIN allOrders c
ON b2.Orders_OrderId = c.orderid
),
mostRecentOrders as (
SELECT *,
MAX(DateOrdered) OVER (PARTITION BY rootId) as [HighestOrderId]
from allOrders
),
pagedOrders as (
select *, dense_rank() over (order by [HighestOrderId] desc) as [PagedRowNumber] from mostRecentOrders)
SELECT * from pagedOrders
where PagedRowNumber between 0 and 2
order by [HighestOrderId] desc
Run Code Online (Sandbox Code Playgroud)
此外,我可以使用MAX(orderid)orderid作为ident和datecreated创建后我的方案中无法更新.
更新了SQLFiddle:http://sqlfiddle.com/#!3/ca6cb/41
将在外部选择工作的 OVER 子句中对 DateOrdered 使用 MAX 吗?
WITH allOrders AS
(
SELECT po.orderid, po.Orders_OrderId, po.DateOrdered, 0 as distance,
row_number() over (order by DateOrdered desc) as RN1
FROM orders po WHERE po.Orders_OrderId is null
UNION ALL
SELECT b2.orderid ,b2.Orders_OrderId, b2.DateOrdered, c.distance + 1,
c.RN1
FROM orders b2
INNER JOIN allOrders c
ON b2.Orders_OrderId = c.orderid
)
SELECT *, MAX(DateOrdered) OVER (PARTITION BY Orders_OrderId) from allOrders
where RN1 between 0 and 2
order by rn1 asc, distance asc
Run Code Online (Sandbox Code Playgroud)
编辑: 抱歉,我第一次误解了您的要求。看起来您想按 RN1 字段而不是 Orders_OrderId 对结果进行分区,因此您的外部选择将类似于..
SELECT MAX(DateOrdered) OVER (PARTITION BY RN1 ),* from allOrders
where RN1 between 0 and 2
order by rn1 asc, distance asc
Run Code Online (Sandbox Code Playgroud)