2017-09-15 5 views
0

3つの列に従ってデータをフィルタリングしたいと思います。sqlフィルタの問題parent_id、id、sort

  • 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。 PARENT_IDのASCでソート

  • nullの場合:

    私は

    • ステップ1 ... ...私はよく分からないCOALESCE機能と優先順位が設定するためのロジックがあると思いステップ2:ライブテストのためのPARENT_ID ASCでソートNULLされていない場合

    データ:http://sqlfiddle.com/#!9/ed850/1


    SOLUTION(教義とsymfonyのために働く)

    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 
    

    あなたの答えのためのライブ結果@quadzzと他人に感謝:私は、これは動作するはずだと思うhttp://sqlfiddle.com/#!9/ed850/4

  • +0

    あなたが唯一のこれまでの階層の1つのレベルがありますか? (いずれの行も*親か子かどちらかであり、決して祖父母関係や深い関係を結ぶことはありません) –

    答えて

    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 
    
    0

    を。

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

    実際には、親のIDの順番を正しく並べる必要があります。これを行うには、RANK()OVERを使用してクエリを実行していますが、メニューや他の階層型組織図など、必要な最上位のレコードについてはparent_ID = nullのみを実行しています。

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

    ランク()今すぐ次のような結果

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

    を返しますによって順序は、すべての詳細がする必要があることを一番上の適切な順序を知っています。 これで、ID = rank IDまたはParent ID = rank 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;