【发布时间】:2014-03-01 11:59:47
【问题描述】:
我有一个具有父/子关系的表以及一个引用自身的创建日期列。 我想显示节点上最近的“活动”排序的每个父记录和所有后代。 因此,如果很久以前创建的第 1 行添加了一个新子代(例如,或者将一个新子代添加到其子代中),那么我希望它位于结果的顶部。
我目前无法使其正常工作。
我的表结构如下:
CREATE TABLE [dbo].[Orders](
[OrderId] [int] NOT NULL,
[Orders_OrderId] [int] NULL,
[DateOrdered] datetime)
我写了下面的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
有什么方法可以“聚合”递归选择的结果,以便在整个“父”节点中选择最大日期?
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
另外,我可以使用 MAX(orderid),因为 orderid 是标识,并且创建日期后无法在我的场景中更新。
更新的 SQLFiddle:http://sqlfiddle.com/#!3/ca6cb/41
【问题讨论】:
-
您使用的是什么版本的 SQL Server?
-
@JonSenchyna SQL 2008
-
@EdW,只需在小提琴中显示给定样本数据的期望输出即可。
-
@KumarHarsh 第二个 SQLFiddle 中有正确的数据。尽管sqlfiddle.com/#!3/9df5e/1 我在这里添加了更多示例数据
标签: sql sql-server tsql recursion