2015-10-16 26 views
8

Mam tabelę zawierającą wartości następującoRekursywnie concat kolumny w sql

╔═══╦════╦════╦══════╦══════╗ 
║ b ║ l1 ║ l2 ║ l3 ║ l4 ║ 
╠═══╬════╬════╬══════╬══════╣ 
║ a ║ b1 ║ c1 ║ d1 ║ e1 ║ 
║ d ║ x1 ║ y1 ║ null ║ null ║ 
╚═══╩════╩════╩══════╩══════╝ 

Wyjście powinno być:

╔═══════════╗ 
║ ab1c1d1e1 ║ 
║ ab1c1d1 ║ 
║ ab1c1  ║ 
║ ab1  ║ 
║ dx1y1  ║ 
║ dx1  ║ 
╚═══════════╝ 

Czy to możliwe? Widzę tutaj wzór, ale jestem w stanie go wymyślić, jak to zrobić. P.S: ROLLUP nie może być używany, ponieważ serwer go nie obsługuje.

Odpowiedz

6

Korzystanie UNION ALL: Plan

SELECT * FROM(
    SELECT b + l1 + l2 + l3 + l4 FROM tbl UNION ALL 
    SELECT b + l1 + l2 + l3 FROM tbl UNION ALL 
    SELECT b + l1 + l2 FROM tbl UNION ALL 
    SELECT b + l1 FROM tbl 
) AS t(a) 
WHERE a IS NOT NULL 

Wykonanie:

enter image description here


Oto kolejny sposób na UNPIVOT, to będzie skanował stół tylko raz

SELECT x.a 
FROM tbl t 
CROSS APPLY(VALUES 
    (b + l1 + l2 + l3 + l4), 
    (b + l1 + l2 + l3), 
    (b + l1 + l2), 
    (b + l1) 
) AS x(a) 
WHERE a IS NOT NULL 
Plan

Wykonanie:

enter image description here

+0

Z ciekawości, czy istnieje sposób na wykonanie tego bez sztywnego kodowania kolumn i wierszy do "WYBIERZ" (tak przy okazji zaznaczyłem to pytanie). –

+1

Skanuje tabelę za każdym razem, gdy zostanie wybrany. A ponieważ jest to xml z tyłu. Będzie kosztowna. Muszę uzyskać wyjście w powiedz 3 do 5 ms na maksimum. – techno

+0

@TimBiegeleisen, może dynamiczny SQL. –

0

EDIT: Ta zwiększona rozwiązanie dostarcza dane jako nagie strun. Jeśli to szybko - nie wiem. Proszę dać mi znać ...

DECLARE @tbl TABLE(b varchar(100),l1 varchar(100),l2 varchar(100),l3 varchar(100), l4 varchar(100)); 
INSERT INTO @tbl VALUES 
('a','b1','c1','d1','e1') 
,('d','x1','y1',null,null); 


SELECT u.v.value('.','varchar(max)') 
FROM 
(
    SELECT '' + b + l1 + l2 + l3 + l4 + ';' AS x 
      ,'' + b + l1 + l2 + l3 + ';'  AS x 
      ,'' + b + l1 + l2 + ';'   AS x 
      ,'' + b + l1 + ';'    AS x 
    FROM @tbl 
    FOR XML PATH(''),TYPE 
) AS XMLList(x) 
CROSS APPLY XMLList.x.nodes('/x') AS a(b) 
CROSS APPLY(SELECT CAST('<r>' + REPLACE(a.b.value('.','varchar(max)'),';','</r><r>') + '</r>' AS XML)) AS m(n) 
CROSS APPLY m.n.nodes('/r') AS u(v) 
WHERE LEN(u.v.value('.','varchar(max)'))> 0 

/* Result 

ab1c1d1e1 
ab1c1d1 
ab1c1 
ab1 
dx1y1 
dx1 

*/ 
+0

Hej, jeśli wstawiam xml do tabeli, samo tworzenie tabeli wymaga czasu, więc nie jest to opcja. Dzięki :) – techno

+0

@TejalKarande, znajdziesz ulepszoną odmianę w mojej odpowiedzi. Rezultatem nie jest już XML, ale - szczerze mówiąc - nie oczekuję, że będzie to szybsze niż odpowiedź Felixa. Byłbym ciekawy, czy to działa ... – Shnugo

+0

Hej .. kiedy porównuję to z krzyżem, twoje zapytanie jest wolniejsze ... Dzięki :) – techno