基于另一列的值按SQL查询排序

基于另一列的值按SQL查询排序,sql,sql-server,Sql,Sql Server,我有这样的桌子: SELECT t1.*, t2.Date FROM TableName t1 INNER JOIN TableName t2 ON t2.ID = t1.ParentId with t as (select 1 id, 'aaa' name, cast('20200907' as date) date, 1 parentid union select 2 id, 'bbb' name, cast('20200908' as date) date, 2 parentid u

我有这样的桌子:

SELECT t1.*, t2.Date
FROM TableName t1
INNER JOIN TableName t2 ON t2.ID = t1.ParentId
with t as 
(select 1 id, 'aaa' name, cast('20200907' as date) date, 1 parentid union
select 2 id, 'bbb' name,  cast('20200908' as date) date, 2 parentid union
select 3 id, 'ccc' name,  cast('20200909' as date) date, 3 parentid union
select 4 id, 'ddd' name,  cast('20200910' as date) date, 4 parentid union
select 5 id, 'eee' name,  cast('20200911' as date) date, 2 parentid union
select 6 id, 'fff' name,  cast('20200912' as date) date, 1 parentid union
select 7 id, 'ggg' name,  cast('20200913' as date) date, 5 parentid union
select 8 id, 'hhh' name,  cast('20200914' as date) date, 3 parentid union
select 9 id, 'iii' name,  cast('20200915' as date) date, 4 parentid union
select 10 id, 'jjj' name, cast('20200916' as date) date, 10 parentid)

, t1 (id, name, date, parentid, level) as (
select id, name, date, parentid, 0 from t where id = parentid  --starting condition (top level, no higher ancestors)
union all
select t.id, t.name, t.date, t.parentid, t1.level + 1 --level goes down
from t join t1 on t.parentid = t1.id --hierarchy condition, add those elements that have a direct ancestor already selected
and t.id != t1.parentid --cannot reselect them, otherwise the recursion won't stop
)

select * from t1 order by level, id

我想根据引用ID的ParentID缩短数据。因此,如果ParentID为5的数据,它将位于ID为5的数据下。这就是我想要的预期数据:

有可能吗?如果可能,如何对这些数据进行排序?
提前感谢。

请尝试使用如下自加入:

SELECT t1.*, t2.Date
FROM TableName t1
INNER JOIN TableName t2 ON t2.ID = t1.ParentId
with t as 
(select 1 id, 'aaa' name, cast('20200907' as date) date, 1 parentid union
select 2 id, 'bbb' name,  cast('20200908' as date) date, 2 parentid union
select 3 id, 'ccc' name,  cast('20200909' as date) date, 3 parentid union
select 4 id, 'ddd' name,  cast('20200910' as date) date, 4 parentid union
select 5 id, 'eee' name,  cast('20200911' as date) date, 2 parentid union
select 6 id, 'fff' name,  cast('20200912' as date) date, 1 parentid union
select 7 id, 'ggg' name,  cast('20200913' as date) date, 5 parentid union
select 8 id, 'hhh' name,  cast('20200914' as date) date, 3 parentid union
select 9 id, 'iii' name,  cast('20200915' as date) date, 4 parentid union
select 10 id, 'jjj' name, cast('20200916' as date) date, 10 parentid)

, t1 (id, name, date, parentid, level) as (
select id, name, date, parentid, 0 from t where id = parentid  --starting condition (top level, no higher ancestors)
union all
select t.id, t.name, t.date, t.parentid, t1.level + 1 --level goes down
from t join t1 on t.parentid = t1.id --hierarchy condition, add those elements that have a direct ancestor already selected
and t.id != t1.parentid --cannot reselect them, otherwise the recursion won't stop
)

select * from t1 order by level, id

您可能希望按层次对所有数据进行排序。这可以最好的方法来完成

在您的情况下,SQL将如下所示:

SELECT t1.*, t2.Date
FROM TableName t1
INNER JOIN TableName t2 ON t2.ID = t1.ParentId
with t as 
(select 1 id, 'aaa' name, cast('20200907' as date) date, 1 parentid union
select 2 id, 'bbb' name,  cast('20200908' as date) date, 2 parentid union
select 3 id, 'ccc' name,  cast('20200909' as date) date, 3 parentid union
select 4 id, 'ddd' name,  cast('20200910' as date) date, 4 parentid union
select 5 id, 'eee' name,  cast('20200911' as date) date, 2 parentid union
select 6 id, 'fff' name,  cast('20200912' as date) date, 1 parentid union
select 7 id, 'ggg' name,  cast('20200913' as date) date, 5 parentid union
select 8 id, 'hhh' name,  cast('20200914' as date) date, 3 parentid union
select 9 id, 'iii' name,  cast('20200915' as date) date, 4 parentid union
select 10 id, 'jjj' name, cast('20200916' as date) date, 10 parentid)

, t1 (id, name, date, parentid, level) as (
select id, name, date, parentid, 0 from t where id = parentid  --starting condition (top level, no higher ancestors)
union all
select t.id, t.name, t.date, t.parentid, t1.level + 1 --level goes down
from t join t1 on t.parentid = t1.id --hierarchy condition, add those elements that have a direct ancestor already selected
and t.id != t1.parentid --cannot reselect them, otherwise the recursion won't stop
)

select * from t1 order by level, id
最终结果是这样的

您可以使用公共表表达式(CTE)首先查询父记录,然后在第二次查询中查询子记录。如果您创建了一个
排序
列,则可以对数据进行完美排序:

create table #temp (
  id int,
  name varchar(10),
  [date] date,
  parentid int
)

insert into #temp values
(1, 'AAA', '9/7/2020', 1),
(2, 'BBB', '9/8/2020', 2),
(3, 'CCC', '9/8/2020', 3),
(4, 'DDD', '9/8/2020', 4),
(5, 'EEE', '9/8/2020', 2),
(6, 'FFF', '9/8/2020', 1),
(7, 'GGG', '9/8/2020', 5),
(8, 'HHH', '9/8/2020', 3),
(9, 'III', '9/8/2020', 4),
(10, 'JJJ', '9/8/2020', 10)

;with cte (id, parentid, name, [date], sort) as
(
  /* query #1 : pull only parent records */
  select id, parentid, name, [date],
         cast(right('0000' + cast(row_number() over (order by id) as varchar(5)), 5) as varchar(1024))
  from   #temp
  where  id = parentid                           /* pull just the parent records */

  union all

  /* query #2 : add children records */
  select t.id, t.parentid, t.name, t.[date],
         cast(c.sort + right('0000' + cast(row_number() over (order by t.id) as varchar(5)), 5) as varchar(1024))
  from   cte c                                   /* include data from 1st query */
         inner join #temp t on c.id = t.parentid /* only pull children of the parent records returned in query #1 */
  where  t.id <> t.parentid                      /* a record cannot be a child of itself, prevents infinite recursion */
)
select *
from   cte
order by sort

drop table #temp
关键是
sort
列,它构建了一个可以按字母顺序排序的值。当然,您可以从最终输出中排除
sort
列,但我想让您看看它是如何构建排序数据的


CTE查询的递归性质意味着它将继续循环并重新运行子查询,直到所有子查询+孙子查询+曾孙查询等都被提取出来。这就是为什么
GGG
记录的
sort
数据包含3部分数据的原因。

在一个简单的数据集上,这个数据集是一个具有有限数量的小级别的层次结构,您可以通过简单的自连接来实现这一点

如果数据库引擎不支持
CTE
s,或者需要简化查询维护,则可以使用此方法代替
CTE

使用表变量设置

@表
中进行3级深度的查询

如果您的数据结构中有空值表示没有父项,那么此查询可能会更有效,但我们必须合并ID:

SELECT child.id, child.name, child.[date], child.parentId
FROM @table child
LEFT OUTER JOIN @table parent on child.parentid = parent.id
order by COALESCE(parent.parentid,child.parentid,child.Id), IsNull(child.parentid,child.Id), child.id
最后,要支持每个额外的递归级别,请添加另一个联接,最终需要
n-2
联接,其中
n
是数据支持的最大级别数,以下支持4个级别:

SELECT child.id, child.name, child.[date], child.parentId
FROM @table child
LEFT OUTER JOIN @table parent on child.parentid = parent.id
LEFT OUTER JOIN @table grandparent on parent.parentid = grandparent.id
order by COALESCE(grandparent.parentId, parent.parentid,child.parentid,child.Id), COALESCE(parent.parentid,child.parentid,child.Id), IsNull(child.parentid,child.Id), child.id

我只有一张桌子。如果我只有一个表,我必须加入吗?我已经尝试了该查询,但仍然无法显示所需的预期数据。但是,谢谢你的回答。@Alex:查询缺少订单,原因是。。。您需要添加“orderbyt2.[parentid],t1.[id]”并删除t2.Date,它应该可以正常工作感谢您的帮助回答我的问题。我尝试过这个查询,它对我很有效。