2013-08-29 40 views
2

我有一些ROWS有1到6個值。例如:如何將3個值應用於每行1行至3行?

Param1: A|B|C|D 
Param2: B|Y 
Param3: A 

我需要改變這樣的:

Param1: A 
Param1: B 
Param1: C 
Param1: D 
Param2: B 
Param2: Y 
Param3: A 

嗯,我想一個樞軸UNPIVOT可能會奏效,但也有很多我需要的條件和領域。此外,我有一個視圖,將所有值分開並統計它們。在頂部例如,它會返回數據集是這樣的:

A 2 
B 2 
C 1 
D 1 
Y 1 

這是我自己的例子,這是在幾個記錄好嗎工作,並與超過10萬行非常糟糕的作品。

最初的故事就是這個。我有一些對象(obj),每個都有它的params(prm),它們的值(val)。所以,如你所見,每個對象就像一棵樹,我需要擴展它。 這裏是一個仿真:

DECLARE @x TABLE 
    (
     prm INT , 
     iin VARCHAR(20) , 
     oout VARCHAR(20) 
    ) 
INSERT INTO @x 
VALUES (1, 'A/B/C', 'A') 
INSERT INTO @x 
VALUES (1, 'A/B/C', 'B') 
INSERT INTO @x 
VALUES (1, 'A/B/C', 'C') 
INSERT INTO @x 
VALUES (3, 'D', 'D') 
INSERT INTO @x 
VALUES (2, 'R/G', 'R') 
INSERT INTO @x 
VALUES (2, 'R/G', 'G') 

DECLARE @y TABLE 
    (
     obj INT , 
     prm INT , 
     val VARCHAR(20) 
    ) 
INSERT INTO @y 
VALUES (10, 1, 'A/B/C') 
INSERT INTO @y 
VALUES (10, 2, 'R/G') 
INSERT INTO @y 
VALUES (10, 3, 'D') 
INSERT INTO @y 
VALUES (20, 2, 'R/G') 
INSERT INTO @y 
VALUES (20, 3, 'D') 

DECLARE @z TABLE 
    (
     id INT , 
     obj INT , 
     prm INT , 
     val VARCHAR(20) 
    ) 
INSERT INTO @z 
VALUES (1, 10, 1, NULL) 
INSERT INTO @z 
VALUES (2, 10, 1, NULL) 
INSERT INTO @z 
VALUES (3, 10, 1, NULL) 
INSERT INTO @z 
VALUES (4, 10, 2, NULL) 
INSERT INTO @z 
VALUES (5, 10, 2, NULL) 
INSERT INTO @z 
VALUES (6, 10, 3, NULL) 
INSERT INTO @z 
VALUES (7, 20, 2, NULL) 
INSERT INTO @z 
VALUES (8, 20, 2, NULL) 
INSERT INTO @z 
VALUES (9, 20, 3, NULL) 

而決定:

; 
WITH a AS (SELECT ROW_NUMBER() OVER (PARTITION BY prm ORDER BY prm) n , 
        * 
      FROM  @x 
     ), 
    b AS (SELECT ROW_NUMBER() OVER (PARTITION BY obj, prm ORDER BY obj, prm) n , 
        * 
      FROM  @z 
     ) 
UPDATE b 
SET  b.val = a.oout 
FROM b 
     INNER JOIN @y y ON y.obj = b.obj 
          AND y.prm = b.prm 
     INNER JOIN a ON a.n = b.n 
         AND a.prm = b.prm 
         AND y.val = a.iin 
SELECT * 
FROM @z 

@y表 - 是與像第一實施例,其中參數1,參數2是在柱1,2 ETS參數的表PRM,關於OBJ
一些對象@z表 - 是仿真VAL設置爲NULL,其表示,什麼PARAMS應該充滿值
@x表 - 是一個模擬值的除法,這應該適用於@y表,替換的空值@ z具有實際排名值的表。

有沒有更好的方法來做到這一點?

回答

2

那麼我不會給你一個完整的解決方案,但如果我需要這樣的分割數據,我會嘗試使用sqlxml(你必須在大量的行上嘗試它來檢查性能是否正常) :

declare @x table (prm int,iin varchar(20)) 

insert into @x values(1, 'A/B/C') 
insert into @x values(3, 'D') 
insert into @x values(2, 'R/G') 

select 
    x.prm, x.iin, T.C.value('.', 'nvarchar(max)') as oout 
from @x as x 
    outer apply (
     select cast('<d>' + replace(x.iin, '/', '</d><d>') + '</d>' as xml) as Data 
    ) as D 
    outer apply D.Data.nodes('d') as T(C) 

參見sql fiddle demo來嘗試它。

+0

+1,我不知道這是否是一個最佳的解決方案,當數據集很大但工作時,並且是將字段按字符分隔成不同行的好方案。 (在這種情況下 」/」)。非常感謝。 –

+1

在我看來,如果你需要經常做,最好寫clr regex split函數,但對於小數據xml工作正常。 –

+0

嗯,首先謝謝!但是有一個問題。我永遠不知道會是哪種分離。你看 - 一個提供者給我一個100億行的列表(這意味着帶有參數和值列表的對象)。並從我身邊有預定義的參數和值。手動我將提供者列表中的參數鏈接到我的數據庫中的參數。價值觀也是如此。最後 - 我從我的數據庫表中獲取數據,而不是使用值本身的字符串。這就是爲什麼sqlxml不適合。它不可能僅以數據作爲字符串工作。但是,請不要猶豫,再寫一遍!tnx – notricky