繁体   English   中英

Order By SQL 根据值查询另一列

[英]Order By SQL Query based on Value another Column

我有这样的表:

当前表

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

预期表

有可能这样做吗? 如果可能,如何订购该数据? 先感谢您。

您可以使用公用表表达式 (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

最终结果看起来像这样显示 parentid-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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM