Column 1:
| word1 word2 word3 word4 |
到
Col 1: Col 2: Col 3: Col 4:
| word1 | word2 | word3 | word |
是否有可能不同的單詞或短語從一個字符串爲多列分開?字符串中的所有單詞和短語通常由雙空格分隔,沒有別的。是否有預定義的函數可以從SQL Server中使用,例如CAST或INTERSECT,還是必須自己編寫?
Column 1:
| word1 word2 word3 word4 |
到
Col 1: Col 2: Col 3: Col 4:
| word1 | word2 | word3 | word |
是否有可能不同的單詞或短語從一個字符串爲多列分開?字符串中的所有單詞和短語通常由雙空格分隔,沒有別的。是否有預定義的函數可以從SQL Server中使用,例如CAST或INTERSECT,還是必須自己編寫?
這裏是一個動態的SQL版本。約翰的情況下,如果你不知道最大的單詞數量。實現你想要的關鍵技術將是拆分字符串和數據透視(或條件聚合)。因爲你有兩種做法,約翰的方法是一個很好的捷徑。
IF OBJECT_ID('tempdb..#TblName') IS NOT NULL
BEGIN
DROP TABLE #TblName
END
CREATE TABLE #TblName (
ID INT IDENTITY(1,1)
,String VARCHAR(500)
)
INSERT INTO #TblName VALUES ('word1 word2 word3 word4'),('abcd efgh ijkl')
DECLARE @NumWords INT
SELECT @NumWords = ISNULL(MAX((LEN(String) - LEN(REPLACE(String,' ','')))/2 + 1), 0)
FROM
#TblName
DECLARE @i INT = 1
DECLARE @SQL NVARCHAR(MAX)
SET @SQL = '
SELECT
t.Id
,t.String
,c.*
FROM
#TblName t
CROSS APPLY (
SELECT
'
WHILE @i <= @NumWords
BEGIN
SET @SQL = @SQL
+ IIF(@i > 1,', ','')
+ 'Column' + CAST(@i AS NVARCHAR(MAX)) + '1 = x.value (''/x[' + CAST(@I AS NVARCHAR(MAX)) + ']'',''varchar(max)'')'
SET @i = @i + 1
END
SET @SQL = @SQL + '
FROM
(SELECT CAST(''<x>'' + REPLACE(String,'' '',''</x><x>'') + ''</x>'' as XML) x) a
) c'
EXECUTE (@SQL)
在CROSS APPLY和一些XML的幫助下。易於擴展和/或合同
Declare @YourTable table (id int,Column1 varchar(max))
Insert Into @YourTable values
(1,'word1 word2 word3 word4'),
(2,'some other words')
Select A.ID
,B.*
From @YourTable A
Cross Apply (
Select Pos1 = xDim.value('/x[1]','varchar(max)')
,Pos2 = xDim.value('/x[2]','varchar(max)')
,Pos3 = xDim.value('/x[3]','varchar(max)')
,Pos4 = xDim.value('/x[4]','varchar(max)')
,Pos5 = xDim.value('/x[5]','varchar(max)')
,Pos6 = xDim.value('/x[6]','varchar(max)')
,Pos7 = xDim.value('/x[7]','varchar(max)')
,Pos8 = xDim.value('/x[8]','varchar(max)')
,Pos9 = xDim.value('/x[9]','varchar(max)')
From (Select Cast('<x>' + Replace(A.Column1,' ','</x><x>')+'</x>' as XML) as xDim) A
) B
返回
這非常好,但問題是我沒有定義單詞列表;原始列有多行,每行都有不同的字符串,並且我不能逐個寫下每個字符串,因此函數需要自動執行,尤其是因爲字符串可能與每個帳戶不同,並且每天都會更改。有沒有辦法讓你的函數更具動態性,所以它可以運行多個變量? –
@ K.Ventura(at)YourTable是一個演示表變量。用您的實際表名和A.Column1替換(在)YourTable與您的實際字段名稱,它將運行。當你說動態到底在找什麼時, –
如果字數不固定numbr,您可以使用動態腳本,但這真是一個樣本:
IF OBJECT_ID('tempdb..#tb') IS NOT NULL DROP TABLE #tb
CREATE TABLE #tb (id int,Column1 varchar(max))
insert Into #tb values
(1,'word1 word2 word3 word'),
(2,'w1 w2 w3 w4 w5 w6')
DECLARE @Cols NVARCHAR(max),@sql nvarchar(MAX)
DECLARE @MaxWordCount INT
SELECT @MaxWordCount=MAX(LEN(t.Column1)-len(replace(t.Column1,' ',''))+1) from #tb as t
SELECT @Cols=ISNULL(@Cols+',','')+'[Col '+LTRIM(sv.number)+']' FROM master.dbo.spt_values as sv WHERE sv.Type='P' and sv.number BETWEEN 1 AND @MaxWordCount
PRINT @Cols
SET @sql='SELECT * from (
SELECT t.*, w.* FROM #tb AS t
CROSS APPLY (VALUES (convert(XML, ''<n>'' + replace(t.Column1, '' '', ''</n><n>'') + ''</n>''))) x(c)
CROSS APPLY (SELECT ''Col '' + ltrim(row_number()OVER (ORDER BY getdate())) AS col
,s.b.value(''.'', ''varchar(200)'') AS wd
FROM x.c.nodes(''n'') s(b)) w
) a PIVOT (max(wd) for col in ('[email protected]+')) p'
PRINT @sql
EXEC(@sql)
IF OBJECT_ID('tempdb..#tb') IS NOT NULL DROP TABLE #tb
id Column1 Col 1 Col 2 Col 3 Col 4 Col 5 Col 6 2 w1 w2 w3 w4 w5 w6 w1 w2 w3 w4 w5 w6 1 word1 word2 word3 word word1 word2 word3 word NULL NULL
這個怎麼樣?
Create Table AllData (Column0 varchar(500))
Insert Into AllData Values ('word1 word2 word3 word4')
Select parsename(replace(replace(replace([Column0],' ',' '),' ',' '),' ','.'), 4) [Col1],
parsename(replace(replace(replace([Column0],' ',' '),' ',' '),' ','.'), 3) [Col2],
parsename(replace(replace(replace([Column0],' ',' '),' ',' '),' ','.'), 2) [Col3],
parsename(replace(replace(replace([Column0],' ',' '),' ',' '),' ','.'), 1) [Col4]
from AllData
最大的列數是4,所以總是有4列,但是如果一個字符串只有3個字,那麼只有3個新列將用於該行。你的函數非常好,但是我可以輸入列名作爲插入的值,還是必須一個一個地寫下每個單詞?原始列中的每一行對於每一行都有一組不同的單詞,並且有時單詞每天或每週都會更改,因此我無法每次都重新輸入所有單詞,因此有沒有辦法使您的函數能夠從原始專欄? –
如果最多有4列,我會使用約翰的答案,因爲這將是矯枉過正。我不會按照你的意思寫下每個單詞,因爲這些作品會自動分割出來。你可能會被拋棄,因爲我給列命名爲word1,word2等。所以我只是更新並將其更改爲Column,希望能夠消除混淆。 – Matt