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

时间:2020-07-09 07:18:32

标签: sql sql-server

我有这样的桌子:

Current Table

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

Expected Table

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

4 个答案:

答案 0 :(得分:1)

您可以使用公用表表达式(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列,该列建立可以按字母顺序排序的值。当然,您可以从最终输出中排除sort列,但我希望您了解它如何构建排序数据。

CTE查询的递归性质意味着它将继续循环并重新运行子查询,直到所有子级+孙级+大孙级等都被拉出为止。这就是sort记录的GGG数据具有3部分数据的原因。

答案 1 :(得分:0)

请尝试使用这种自我连接:

SELECT t1.*, t2.Date
FROM TableName t1
INNER JOIN TableName t2 ON t2.ID = t1.ParentId

答案 2 :(得分:0)

您可能希望对所有数据进行分层排序。最好使用CTE's

在您的情况下,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

最终结果如下所示 showing the hierarchy and levels of the parentid-id relations

答案 3 :(得分:0)

在一个简单的数据集上,该数据集是一个级别有限且层次很小的层次结构,您可以通过简单的自我连接来实现。

如果您的数据库引擎不支持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)

@table进行3级深度查询

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
相关问题