sql过滤parent_id,id和sort的问题

时间:2017-09-15 14:21:22

标签: sql sorting filter

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

  • PARENT_ID
  • 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

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

我认为这应该有用。

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

答案 2 :(得分:0)

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

#include <cstring>
#include "MyStrCopy.h"

void MyStrCopy(char* dest, const char* source, int dest_len) {
    strncpy(dest, source, dest_len);
    dest[dest_len-1] = 0; // zero terminated when source > dest
}

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

char* MyStrCopy(char* dest, const char* source, int dest_len) {
    return strncpy(dest, source, dest_len);
}

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

主要排序基于ParentRanked预查询的xRANK列,然后基于此后的正常排序。生成的查询是......

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