2016-04-19 7 views
0

Ich habe eine exportierte Tabelle aus Buchhaltungssoftware wie unten.Erstellen Sie Baum Abfrage aus Numerische Mapping-Tabelle in SQL

AccountID  AccountName  
---------  ----------- 
11   Acc11 
12   Acc12 
13   Acc13 
11/11   Acc11/11 
11/12   Acc11/12 
11/111  Acc11/111 
11/11/001  Acc11/11/001 
11/11/002  Acc11/11/002 
12/111  Acc12/111 
12/112  Acc12/112 

dann will ich es Baum Abfrage in MS-SQL-Server 2008 konvertieren als TreeList Datenquelle in meinem Sieg aaplication zu verwenden.

Erwartete SQL-Abfrage Ergebnis:

AccountID  AccountName ID ParentID Level HasChild 
---------  ----------- --- --------- ------ -------- 
11   Acc11   1  Null  1  1 
12   Acc12   2  Null  1  1 
13   Acc13   3  Null  1  0 
11/11   Acc11/11  4  1   2  1 
11/12   Acc11/12  5  1   2  0 
11/111  Acc11/111  6  1   2  0 
11/11/001  Acc11/11/001 7  4   3  0 
11/11/002  Acc11/11/002 8  4   3  0 
12/111  Acc12/111  9  2   2  0 
12/112  Acc12/112  10 2   2  0 

Würden Sie mir bitte helfen SQL-Abfrage für das Erstellen? Danke.

+0

Welche Version von SQL Server? – Shnugo

+0

ist es SQL Server 2008. –

Antwort

1

keine Zweifel, was query Sie schreibe oder was auch immer DBA DO, Ihre Abfrage wird wegen fehlerhafter Tabellenstruktur langsam sein.

Ich glaube, Ihre obige Abfrage funktioniert auch für andere Beispieldaten.

In einer solchen Situation, ich hole meinen Datensatz im Front-End wie (C# etc) und tun Manipulation dort, um Wunsch Ausgabe zu erhalten, ist es oft schnell in solchen Fällen.

Ich habe versucht, Abfrage auf meine eigene Art zu schreiben, hoffe, es ist schnell für 6000 Datensätze. Auch bitte meine Abfrage für andere Beispieldaten auch.

Ich finde lastIndexOf ("/"), dann

DECLARE @FilePath VARCHAR(50) = '11/11/001' 
DECLARE @FindChar1 VARCHAR(1) = '/' 

SELECT substring (@FilePath,0, LEN(@FilePath) - CHARINDEX(@FindChar1,REVERSE(@FilePath))+1)AS LastOccuredAt 

Schluss Abfrage beitreten

DECLARE @tbl TABLE(id int identity(1,1), AccountID VARCHAR(100), AccountName VARCHAR(100)); 
INSERT INTO @tbl VALUES 
('11','Acc11') 
,('12','Acc12') 
,('13','Acc13') 
,('11/11','Acc11/11') 
,('11/12','Acc11/12') 
,('11/111','Acc11/111') 
,('11/11/001','Acc11/11/001') 
,('11/11/002','Acc11/11/002') 
,('12/111','Acc12/111') 
,('12/112','Acc12/112'); 


DECLARE @FindChar VARCHAR(1) = '/' 


    SELECT a.id 
     ,a.accountid 
     ,a.AccountName 
     ,(
      SELECT min(c.id) 
      FROM @tbl c 
      WHERE c.id < a.id 
       AND substring(a.accountid, 0, LEN(a.accountid) - CHARINDEX(@FindChar, REVERSE(a.accountid)) + 1) = c.accountid 
      ) ParentID 
     ,LEN(a.AccountID) - LEN(REPLACE(a.AccountID, '/', '')) + 1 AS [level] 
     ,(
      SELECT CASE 
        WHEN min(c.id) IS NOT NULL 
         THEN 1 
        ELSE 0 
        END 
      FROM @tbl c 
      WHERE c.id > a.id 
       AND substring(c.accountid, 0, LEN(c.accountid) - CHARINDEX(@FindChar, REVERSE(c.accountid)) + 1) = a.accountid 
      ) Haschild 
    FROM @tbl a 
    INNER JOIN @tbl b ON a.id = b.id + 1 
+0

Es funktioniert so gut wie möglich! Groß! Danke vielmals. –

1

Sie vielleicht einen Blick auf HIERARCHYID haben ... http://searchsqlserver.techtarget.com/tip/How-to-use-SQL-Server-2008-hierarchyid-data-type

Aber dies war ein Ansatz ...

DECLARE @tbl TABLE(AccountID VARCHAR(100), AccountName VARCHAR(100)); 
INSERT INTO @tbl VALUES 
('11','Acc11') 
,('12','Acc12') 
,('13','Acc13') 
,('11/11','Acc11/11') 
,('11/12','Acc11/12') 
,('11/111','Acc11/111') 
,('11/11/001','Acc11/11/001') 
,('11/11/002','Acc11/11/002') 
,('12/111','Acc12/111') 
,('12/112','Acc12/112'); 

WITH shreddAccountID AS 
(
    SELECT AccountName,AccountID 
      ,ROW_NUMBER() OVER(ORDER BY LEN(AccountID)-LEN(REPLACE(AccountID,'/','')),AccountID) AS ID 
      ,LEN(AccountID)-LEN(REPLACE(AccountID,'/','')) + 1 As [Level] 
      ,CAST('<x>' + REPLACE(AccountID,'/','</x><x>') + '</x>' AS XML) AS Shredded 
    FROM @tbl 
) 
,RecursiveCTE AS 
(
    SELECT AccountID,AccountName,ID,[Level],Shredded.value('/x[sql:column("Level")][1]','int') AS innerID,CAST(NULL AS BIGINT) AS ParentID 
    FROM shreddAccountID WHERE [Level]=1 
    UNION ALL 
    SELECT sa.AccountID,sa.AccountName,sa.ID,sa.[Level],sa.Shredded.value('/x[sql:column("sa.Level")][1]','int'),r.ID 
    FROM RecursiveCTE AS r 
    INNER JOIN shreddAccountID AS sa ON sa.Level=r.Level+1 
             AND r.innerID=sa.Shredded.value('/x[sql:column("sa.Level")-1][1]','int') 
) 
SELECT r.AccountID 
     ,r.AccountName 
     ,r.ID 
     ,r.ParentID 
     ,r.[Level] 
     ,CASE WHEN EXISTS(SELECT 1 FROM RecursiveCTE AS x WHERE r.ID = x.ParentID) THEN 1 ELSE 0 END AS HasChild 
FROM RecursiveCTE AS r 
ORDER BY [Level],ParentID 

Das Ergebnis

+-----------+--------------+----+----------+-------+----------+ 
| AccountID | AccountName | ID | ParentID | Level | HasChild | 
+-----------+--------------+----+----------+-------+----------+ 
| 11  | Acc11  | 1 | NULL  | 1  | 1  | 
+-----------+--------------+----+----------+-------+----------+ 
| 12  | Acc12  | 2 | NULL  | 1  | 1  | 
+-----------+--------------+----+----------+-------+----------+ 
| 13  | Acc13  | 3 | NULL  | 1  | 0  | 
+-----------+--------------+----+----------+-------+----------+ 
| 11/11  | Acc11/11  | 4 | 1  | 2  | 1  | 
+-----------+--------------+----+----------+-------+----------+ 
| 11/111 | Acc11/111 | 5 | 1  | 2  | 0  | 
+-----------+--------------+----+----------+-------+----------+ 
| 11/12  | Acc11/12  | 6 | 1  | 2  | 0  | 
+-----------+--------------+----+----------+-------+----------+ 
| 12/111 | Acc12/111 | 7 | 2  | 2  | 0  | 
+-----------+--------------+----+----------+-------+----------+ 
| 12/112 | Acc12/112 | 8 | 2  | 2  | 0  | 
+-----------+--------------+----+----------+-------+----------+ 
| 11/11/001 | Acc11/11/001 | 9 | 4  | 3  | 0  | 
+-----------+--------------+----+----------+-------+----------+ 
| 11/11/002 | Acc11/11/002 | 10 | 4  | 3  | 0  | 
+-----------+--------------+----+----------+-------+----------+ 
+0

Tanks für Ihre Antwort. Ich habe nachgeschaut. Es ist Arbeit, aber es ist sehr, sehr langsam. Zum Beispiel für die Top 500 Datensätze meiner Tabelle, es dauert 116 Sekunden und ich denke, mit all meinen Aufzeichnungen (ungefähr 6000) ist es nicht anwendbar. Gibt es eine schnellere Lösung? –

+1

@R.Salehi Es ist deine Struktur, die es langsam macht ... Eigentlich habe ich einige Ideen, wie man das nach einigen strukturellen Verbesserungen beschleunigen kann, aber das ist zu viel für hier ... Ich würde dir folgendes vorschlagen: Als Meine Antwort löst die gegebene Frage, bitte stimme sie ab und akzeptiere sie. Dann starte eine neue Frage (etwa wie * Wie kann ich die Struktur meiner Tabelle ändern, um eine schnellere Hierarchierelation zu erhalten? * Mit einem Link dazu und Sie erhalten innerhalb von Minuten eine helfende Armada. – Shnugo

+0

Stimmt, vielen Dank für Ihre Hilfe. :) –

Verwandte Themen