按日期对父行进行排序,每行按行独立排序

时间:2012-08-08 03:31:50

标签: sql sql-server-2008 sql-order-by inner-join common-table-expression

这是我的表架构的一个人为的版本来说明我的问题:

QuoteID,Details,DateCreated,ModelQuoteID

其中QuoteID是主键,而ModelQuoteID是一个可以为空的外键,返回到此表以表示已建模的另一个引号(并且可能随后更改了其详细信息列等)。

我需要返回由DateCreated降序排序的引号列表,但建模引号除外,它应位于其父引号之下,按日期降序排列在任何其他同级引号内(引号只能建模一级深度)。

例如,如果我有这4行报价:

1, 'Fix the roof', '01/01/2012', null
2, 'Clean the drains', '02/02/2012', null
3, 'Fix the roof and door', '03/03/2012', 1
4, 'Fix the roof, door and window', '04/04/2012', 1
5, 'Mow the lawn', '05/05/2012', null

然后我需要按顺序返回结果:

5 - Mow the lawn
2 - Clean the drains
1 - Fix the roof
4 - -> Fix the roof, door and window
3 - -> Fix the roof and door

我也传递了搜索条件,例如详细信息的关键字,即使它们不包含搜索字词,但我的父引用也会返回模型引号。我已经使用公共表表达式来使用该部分来获取原始引号,并与建模的连接联合。

这很好用,但是目前我不得不将建模的引号重新排列成代码中的正确顺序。这并不理想,因为我的下一步是在SQL中实现分页,如果那时行没有正确分组,那么我不会让当前页面中的子代在代码中进行重新排序。一般来说,无论如何它们将自然地组合在一起,但并非总是如此。您可以在今天为一个月前的报价创建模型报价。

我花了很多时间在这上面,任何SQL专家都能帮忙吗?非常感谢。

编辑:这是我的SQL的一个人为的版本,以适应我的人为例子: - )

;with originals as (
select
    q.*
from
    Quote q
where
    Details like @details
)
select
    *
from
(
select
    o.*
from
    originals o

union

select
    q2.*
from
    Quote q2
join
    originals o on q2.ModelQuoteID = o.QuoteID
)
as combined

order by
    combined.CreatedDate desc

1 个答案:

答案 0 :(得分:4)

观看奥运会 - 只是略过了你的帖子 - 看起来你想要控制每个级别的排序(根和一个级别),并确保数据与孩子直接在其父级下方返回(所以你可以分页数据......)。我们一直这样做。您可以为每个内部查询添加order by并创建sort列。我设计了一个稍微不同的例子,应该很容易适用于你的情况。我将根升序和一级降序排序,以说明如何控制每个部分。

declare @tbl table (id int, parent int, name varchar(10))

insert into @tbl (id, parent, name)
values (1, null, 'def'), (2, 1, 'this'), (3, 1, 'is'), (4, 1, 'a'), (5, 1, 'test'),
       (6, null, 'abc'), (7, 6, 'this'), (8, 6, 'is'), (9, 6, 'another'), (10, 6, 'test')

;with cte (id, parent, name, sort) as (
  select id, parent, name, cast(right('0000' + cast(row_number() over (order by name) as varchar(4)), 4) as varchar(1024))
  from   @tbl
  where  parent is null

  union all

  select t.id, t.parent, t.name, cast(cte.sort + right('0000' + cast(row_number() over (order by t.name desc) as varchar(4)), 4) as varchar(1024))
  from   @tbl t inner join cte on t.parent = cte.id
)
select * from cte
order by sort

这会产生以下结果:

id    parent    name     sort
----  --------  -------  ----------
6     NULL      abc      0001
7     6         this     00010001
10    6         test     00010002
8     6         is       00010003
9     6         another  00010004
1     NULL      def      0002
2     1         this     00020001
5     1         test     00020002
3     1         is       00020003
4     1         a        00020004

您可以看到根节点按升序排序,内部节点按降序排序。