2017-03-14 88 views
0

我有一個長字符串的列。數據需要分割成列,並且有不同長度的字符串,並不總是相同數量的列。不完全確定如何做到這一點,所以在這裏尋找一些建議。從字符串拆分數據到列

可以說我有這個字符串:

VS5〜MedCond1〜35.4 | VS4〜MedCond2〜16 | VS1〜MedCond3〜155 | VS2〜MedCond4〜70 |血氧飽和度〜MedCond5〜100 | VS3〜MedCond6〜64 |的FiO2〜MedCond7〜21 | MAP〜MedCond8〜98 |

而在某些情況下,字符串可能並不具備所有的醫療條件,只是其中的一些。

我需要拆分成多列,其中列名在tilds之間,即MedCond1和值將是價值的tild的權利,但在管前,最終是這樣的:

MedCond1 MedCond2 MedCond3 MedCond4 MedCond5 MedCond6 MedCond7 MedCond8 
    ======== ======== ======== ======== ======== ======== ======== ======== 
    35.1  24  110  64  100  88  21  79 

我需要爲大表內的很多行執行此操作,正如我所說的,並非所有列都始終存在,但它們不會是不同的名稱,您可能需要med cond 1-8,然後在另一組中有med cond 3,4,7.

這是我創建的一個查詢,它是我想要的但不是動態的,因此它正在拾取值的一些額外的位串

select MainCol, case when charindex('MedCond1', MainCol) > 0 then 
substring(MainCol, charindex('MedCond1', MainCol) + 9, 4) end as [MedCond1] 
from MedTable 

將返回

MedCond1 
======== 
35.3 
40.2 
33.6 
33|V <--- Problem 

正如你所看到的數值有時拿起以字符串的附加部分,由於CHARINDEX數的硬編碼。該值有時有4個字符長,有一個小數位,有時2個長而沒有小數位。我想使這個動態。管道定義了我需要的數據的結束,並且開始由列名稱末尾的tild定義。

感謝進行此動態

安德魯

+0

過寬。請指定您計劃使用哪個工具來拆分這些字符串 –

+0

希望能夠使用SQL Server 2012 – Andrew

+0

任何人都可以提出任何建議,因爲我正在嘗試完成這個任務的截止日期?我將添加一個我已經完成的sql語句,但它並不是動態的,因此會獲取字符串的其他位。 – Andrew

回答

0

確定任何想法,讓我來刺這個。我概述的解決方案不會純粹是SQL Server,但是它使用文本文件的往返行程。

該方法使用以下步驟:

  1. 逆透視通過管道符號限定的數據(以創建輸出的一個以上的線爲每個輸入線)
  2. 往返將數據從SQL Server轉換爲文本文件並返回
  3. 單獨將數據轉換爲波浪號上的列~符號分隔符
  4. 透視將數據回列

這種方法的主要好處是逆轉置操作,讓你自然缺少一個相當於行來處理像MedCond2缺少的列。它也消除了幾乎所有的字符串操作,除了下面步驟1中的一個REPLACE函數外。

給定一個行的內容如下所示:

VS5~MedCond1~35.4|VS4~MedCond2~16|VS1~MedCond3~155|VS2~MedCond4~70|SPO2~MedCond5~100|VS3~MedCond6~64|FiO2~MedCond7~21|MAP~MedCond8~98| 

步驟1(逆透視):查找和換行符替換管道符號的所有實例。所以,REPLACE(column, '|', CHAR(13))會給你文字的單個輸入行以下行(即在一個單一的數據庫行多行文本):

VS5~MedCond1~35.4 
VS4~MedCond2~16 
VS1~MedCond3~155 
VS2~MedCond4~70 
SPO2~MedCond5~100 
VS3~MedCond6~64 
FiO2~MedCond7~21 
MAP~MedCond8~98 

步驟2(往返):寫在上面的輸出(SSIS,SQLCMD等),並確保定義的換行符與步驟1中的REPLACE命令中使用的換行符相同。

此步驟的目的是爲了連接同一行內的多行與不同行中的其他行。

請注意,步驟1可以通過將管道符號的步驟2 & 3的行分隔符定義來消除。我已經使用換行符進行了附加步驟1,以便更容易理解和調試。

步驟3(獨立的列):使用相同的工具導入的文本文件返回到SQL Server和定義列定界符作爲波浪~符號,行定界符相同的步驟1/2。

ColA MedCondTitle MedCondValue 
------ ------------- ------------- 
VS5 MedCond1  35.4 
VS4 MedCond2  16 
VS1 MedCond3  155 
VS2 MedCond4  70 
SPO2 MedCond5  100 
VS3 MedCond6  64 
FiO2 MedCond7  21 
MAP MedCond8  98 

步驟4(樞軸):現在你必須樞轉行列的平凡簡單步驟,其可與所述形式的語句實現:

SUM(CASE WHEN MedCondTitle='MedCond1' THEN MedCondValue ELSE 0) as MedCond1 
1

此數據看起來像一張桌子本身。它可能已經作爲xml存儲在SQL Server中。 SQL Server支持xml字段並允許查詢它們。事實上,人們可以嘗試轉換這個字符串到XML,然後嘗試進行查詢:

declare @medTable table (item nvarchar(2000)) 
insert into @medTable 
values ('VS5~MedCond1~35.4|VS4~MedCond2~16|VS1~MedCond3~155|VS2~MedCond4~70|SPO2~MedCond5~100|VS3~MedCond6~64|FiO2~MedCond7~21|MAP~MedCond8~98|'); 

-- Step 1: Replace `|` with <item> tags and `~` with `tag` tags 
-- This will return an xml value for each medTable row 
with items as (
    select xmlField= cast('<item><tag>' 
          + replace( 
            replace(item,'|','</tag></item><item><tag>'), 
            '~','</tag><tag>') 
          + '</tag></item>' as xml) 
    from @medTable 
) 
-- Step 2: Select different tags and display them as fields 
select 
    y.item.value('(tag/text())[1]','nvarchar(20)'), 
    y.item.value('(tag/text())[2]','nvarchar(20)'), 
    y.item.value('(tag/text())[3]','nvarchar(20)') 
from items outer apply xmlField.nodes('item') as y(item) 

結果是:

-------------------- -------------------- ------- 
VS5     MedCond1    35.4 
VS4     MedCond2    16 
VS1     MedCond3    155 
VS2     MedCond4    70 
SPO2     MedCond5    100 
VS3     MedCond6    64 
FiO2     MedCond7    21 
MAP     MedCond8    98 
NULL     NULL     NULL 

這將是更好地執行加載時,這個轉換數據雖然。例如,在C#或SSIS中進行替換並將完整的xml值存儲在數據庫中更容易。

您可以修改此查詢過,生成XML值,並將其存儲在數據庫中:

declare @medTable2 table (xmlField xml) 

with items as (
    select xmlField= cast('<item><tag>' + replace(replace(item,'|','</tag></item><item><tag>'),'~','</tag><tag>') + '</tag></item>' as xml) 
    from @medTable 
) 
insert into @medTable2 
select items.xmlField 
from items 

-- Query the new table from now on 
select 
    y.item.value('(tag/text())[1]','nvarchar(20)'), 
    y.item.value('(tag/text())[2]','nvarchar(20)'), 
    y.item.value('(tag/text())[3]','nvarchar(20)') 
from @medTable2 outer apply xmlField.nodes('item') as y(item) 
+0

非常漂亮,比我的回答更好,它需要更多的步驟! – Phylyp