2017-09-15 1 views
0

Ich möchte meine Daten nach 3 Spalten filtern.Problem mit SQL-Filterung Parent-ID, ID und Sortierung

  • PARENT_ID
  • id
  • Art

Beispiel Basis 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 

Ich möchte dieses Ergebnis erhalten:

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 

Ich versuche mit einer COALESCE Funktion ohne Erfolg: SELECT * FROM menu ORDER BY COALESCE(parent_id, id) ASC, parent_id ASC, sort ASC.

Ich denke, dass es eine Ordnung Logik ist mit COALESCE Funktion Priorität gesetzt werden ... Ich bin nicht sicher ...

  • Schritt 1: sortiert nach parent_id ASC wenn NULL IST
  • Schritt 2: sortiert nach parent_id ASC, wenn NOT NULL

Daten für Live-Test: http://sqlfiddle.com/#!9/ed850/1


SOLUTION (Arbeit für symfony mit Lehre)

Thank @quadzz und andere für Ihre Antworten

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 

Live-Ergebnis: http://sqlfiddle.com/#!9/ed850/4

+0

Sie immer nur eine Ebene der Hierarchie? (Jede Zeile ist * entweder * ein Elternteil oder ein Kind, niemals beide Großeltern oder tiefere Beziehungen) –

Antwort

1

, die den Trick tun sollten:

Daten vorbereiten:

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') 

Und die Sortierung selbst:

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

Ich denke, das sollte funktionieren.

0

Es scheint tatsächlich, dass Sie zuerst einen Self-Join mit der korrekt eingereihten Reihenfolge der Eltern-ID benötigen. Um dies zu tun, führe ich eine Abfrage mit RANK() OVER, aber nur für parent_ID = null für die obersten Datensätze, die Sie wollen (wie Menü oder andere hierarchische Organigramm).

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

Der Rang() und um durch die folgenden Ergebnisse

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

Jetzt zurückkehren, wissen Sie, die meisten Top-richtigen Reihenfolge, dass alle zusätzlichen Details sein müssen. Nehmen Sie nun Ihre gesamte Tabelle mit und verbinden Sie sich mit diesem Ergebnis entweder mit der ID = Rangliste oder der Eltern-ID = Rangliste. Auf diese Weise werden alle NULL-Datensätze, auf denen die Abfrage basiert, im Ergebnis enthalten.

Die primäre Sortierung basiert auf der xRANK-Spalte der ParentRanked-Vorabfrage und basiert dann auf der normalen Sortierung danach. Die resultierende Abfrage ist ...

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; 
Verwandte Themen