[英]Order By SQL Query based on Value another Column
您可以使用公用表表达式 (CTE) 先查询父记录,然后在第二个查询中查询子记录。 如果您创建一个sort
列,那么您可以完美地对数据进行排序:
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
返回此数据集:
id parentid name date sort
----------- ----------- ---------- ---------- ----------------
1 1 AAA 2020-09-07 00001
6 1 FFF 2020-09-08 0000100001
2 2 BBB 2020-09-08 00002
5 2 EEE 2020-09-08 0000200001
7 5 GGG 2020-09-08 000020000100001
3 3 CCC 2020-09-08 00003
8 3 HHH 2020-09-08 0000300001
4 4 DDD 2020-09-08 00004
9 4 III 2020-09-08 0000400001
10 10 JJJ 2020-09-08 00005
关键是sort
列,它构建了一个可以按字母顺序排序的值。 当然,您可以从最终的 output 中排除sort
列,但我想让您看看它是如何构建排序数据的。
CTE 查询的递归性质意味着它将继续循环并重新运行子查询,直到所有的孩子 + 孙 + 曾孙等都被拉出。 这就是为什么GGG
记录的sort
数据有 3 部分数据。
请尝试像这样使用自我加入:
SELECT t1.*, t2.Date
FROM TableName t1
INNER JOIN TableName t2 ON t2.ID = t1.ParentId
您可能希望对所有数据进行分层排序。 这最好用CTE来完成
在您的情况下, SQL 看起来像这样:
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
或者您需要保持查询维护简单,则可以使用此方法代替CTE
。
使用表变量设置
DECLARE @table table (
id int,
name varchar(10),
[date] date,
parentid int
)
insert into @table 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)
从具有 3 个深度级别的@table
查询
SELECT child.id, child.name, child.[date], child.parentId
FROM @table child
LEFT OUTER JOIN @table parent on child.parentid = parent.id
ORDER BY parent.parentid, child.parentid, child.id
如果你的数据结构有空值表示没有父级,那么这个查询可以再次更有效,但我们必须COALESCE
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
最后,为了支持每个额外的递归级别,添加另一个join ,最终您将需要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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.