【问题标题】:Issue with sql filtering parent_id, id and sortsql 过滤 parent_id、id 和排序的问题
【发布时间】:2017-09-26 15:56:47
【问题描述】:

我想根据 3 列过滤我的数据。

  • parent_id
  • 身份证
  • 排序

基本 BDD 示例:

id | parent_id | sort | text
-----------------------------
1  |    NULL   |  3   |  D
2  |     10    |  0   |  AA
3  |    NULL   |  1   |  B
4  |     10    |  2   |  AB
5  |     3     |  0   |  BA
6  |     8     |  0   |  CA
7  |     3     |  2   |  BC
8  |    NULL   |  2   |  C
9  |     3     |  1   |  BB
10 |    NULL   |  0   |  A
11 |     1     |  0   |  DA

我想得到这个结果:

id | parent_id | sort | text
-----------------------------
10 |    NULL   |  0   |  A
2  |     10    |  0   |  AA
4  |     10    |  2   |  AB
3  |    NULL   |  1   |  B
5  |     3     |  0   |  BA
9  |     3     |  1   |  BB
7  |     3     |  2   |  BC
8  |    NULL   |  2   |  C
6  |     8     |  0   |  CA
1  |    NULL   |  3   |  D
11 |     1     |  0   |  DA

我尝试使用COALESCE 函数但没有成功:SELECT * FROM menu ORDER BY COALESCE(parent_id, id) ASC, parent_id ASC, sort ASC

我认为有一个通过COALESCE函数优先级设置的顺序逻辑...我不确定...

  • 第 1 步:如果 IS NULL,则按 parent_id ASC 排序
  • 第 2 步:如果 IS NOT NULL,则按 parent_id ASC 排序

现场测试数据:http://sqlfiddle.com/#!9/ed850/1


解决方案(为 symfony 工作)

感谢@quadzz和其他人的回答

SELECT test.*, 
       ( CASE 
           WHEN test.parent_id IS NULL THEN test.sort 
           ELSE test_1.sort 
         END ) AS test1, 
       ( CASE 
           WHEN test.parent_id IS NULL THEN 1 
           ELSE 0 
         END ) AS test2 
FROM   test AS test 
       LEFT JOIN test AS test_1 
              ON ( test_1.id = test.parent_id )
ORDER  BY test1 ASC, 
          test2 DESC, 
          test.sort ASC

直播结果:http://sqlfiddle.com/#!9/ed850/4

【问题讨论】:

  • 你只有一个层次结构吗? (任何一行都是要么父母或孩子,永远不会同时形成祖父母或更深层次的关系)

标签: sql sorting filter


【解决方案1】:

这应该可以解决问题:

准备数据:

if object_id('tempdb..#t1') is not null drop table #t1
create table #t1
(
    id int,
    parent_id int,
    sort int,
    text varchar(10)
)

insert into #t1
values
(1,null,3,'d'),
(2,10,0,'aa'),
(3,null,1,'d'),
(4,10,2,'d'),
(5,3,0,'d'),
(6,8,0,'d'),
(7,3,2,'d'),
(8,null,2,'d'),
(9,3,1,'d'),
(10,null,0,'d'),
(11,1,0,'d')

还有排序本身:

select *
from #t1 t1
order by 
    case when t1.parent_id is null then t1.sort
    else (
        select sort
        from #t1 innert1
        where innert1.id = t1.parent_id
        ) end,
    case when parent_id is null then 1 end desc,
    sort

【讨论】:

    【解决方案2】:

    我认为这应该可行。

    ORDER BY COALESCE(parent_id, id), 
    case when parent_id is null then 1 else 2 end, 
    sort 
    

    【讨论】:

      【解决方案3】:

      实际上,您似乎首先需要对父 ID 的正确排序顺序进行自联接。为此,我使用 RANK() OVER 运行查询,但仅针对您想要的最顶层记录的 parent_ID = null (例如菜单或其他分层组织结构图)。

      select id, sort, rank() over( order by sort ) as xRank
         from YourTable
         where parent_id is null
      

      Rank() 和 order by 将返回以下结果

      id   sort   xRank
      10   0      1
       3   1      2
       8   2      3
       1   3      4
      

      现在,您知道所有其他详细信息所需的最合适的顺序。 现在,在 ID = 排名 ID 或父 ID = 排名 ID 上将整个表连接回此结果。这样,所有作为查询基础的 NULL 记录都包含在结果中。

      主排序基于 ParentRanked 预查询的 xRANK 列,然后基于正常排序。结果查询是...

      select 
              YT.*,
              ParentRank.id as ParentRankID,
              ParentRank.xRank
          from
              YourTable YT
              JOIN ( select 
                          id, 
                          sort, 
                          rank() over( order by sort ) as xRank
                      from 
                          YourTable
                      where 
                          parent_id is null ) ParentRank
                  on YT.parent_id = ParentRank.id
                  OR YT.id = ParentRank.id
          order by
              ParentRank.xRank,
              YT.Sort;
      

      【讨论】:

        猜你喜欢
        • 2018-05-08
        • 1970-01-01
        • 1970-01-01
        • 2011-10-09
        • 2016-12-02
        • 1970-01-01
        • 2016-11-26
        • 1970-01-01
        • 2012-06-14
        相关资源
        最近更新 更多