2011-03-04 80 views
1

我不知道這是否可能在SQL,如果沒有,我會編程方式做到這一點 - 但它會是巨大的,如果有辦法。拆分在SQL一列,然後查找每一個在另一個表

基本上,我有一個表中的列而它與ID的另一個表中的填充,用逗號分隔的 - 這樣一個領域可能是這樣的:

3,4,9

這些鏈接另一個表,其中上面字段中的數字是行的主鍵。在行中是一個描述,我想向用戶顯示而不是數字。

所以基本上,而不是顯示3,4,9給用戶,我想看看他們的相關描述另一個表。這可能嗎?

回答

1

克里斯,

有一個辦法在T-SQL來做到這一點,它實際上是很容易的。首先,你需要創建一個像下面這樣的函數......(使用基於零的「Tally」cte的全新方法,因爲它不會連接任何分隔符,所以它很快速)。

CREATE FUNCTION dbo.DelimitedSplit8KNEW 
--===== Created by Jeff Moden (Prototype: Testing Still in Progress) 
--===== Define I/O parameters 
     (
     @pString VARCHAR(8000), 
     @pDelimiter CHAR(1) 
     ) 
RETURNS TABLE 
    WITH SCHEMABINDING 
    AS 
RETURN 
WITH 
     E1(N) AS (
       SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
       SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
       SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 
       ),       --10 
     E2(N) AS (SELECT 1 FROM E1 a, E1 b), --100 
     E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10,000 
cteTally(N) AS (
       SELECT 0 UNION ALL 
       SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E4 
       ) 
SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY t.N), 
     ItemValue = SUBSTRING(@pString,t.N+1,ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,t.N+1),0),DATALENGTH(@pString)+1)-t.N-1) 
    FROM cteTally t 
    WHERE t.N BETWEEN 0 AND DATALENGTH(@pString) 
    AND (SUBSTRING(@pString,t.N,1) = @pDelimiter OR t.N = 0) 
; 
GO 

現在,看看如何使用它?讓我們說你有一個唯一的列和您的CSV列的表如下(此建立的數據,以及)。我們所要做的就是CROSS與功能應用原始數據,並奇蹟般地分開準備與另一個表被連接:

--===== This just builds some test data 
    -- and is not a part of the solution 
SELECT * 
    INTO #TestTable 
    FROM (
     SELECT 1,'3,4,9' UNION ALL 
     SELECT 2,'3,2,100' UNION ALL 
     SELECT 3,'14,35,8,21,27,12' 
     ) d (RowNum,CsvValue) 
; 
--===== Split the data out giving the unique RowNum 
    -- from the original data, the element position, 
    -- the the value of the split element. You can 
    -- join this SELECT with a table to get the other 
    -- values. 
SELECT data.RowNum, split.ItemNumber, split.ItemValue 
    FROM #TestTable data 
    CROSS APPLY dbo.DelimitedSplit8KNEW(data.CsvValue,',') split 
; 

下面是輸出...

RowNum  ItemNumber   ItemValue 
----------- -------------------- --------- 
1   1     3 
1   2     4 
1   3     9 
2   1     3 
2   2     2 
2   3     100 
3   1     14 
3   2     35 
3   3     8 
3   4     21 
3   5     27 
3   6     12 

(12 row(s) affected) 
2

您可以編寫表值函數,它的分裂,然後加入您的查找表這一結果。

0

你有興趣改變你的模式嗎?通常,在單個字段中存儲多個數據是一種可怕的做法。一對多的關係似乎更合適。

+0

可悲的是這是一個現在不可能做出這樣的改變。這是我幾個月以前設計的,當時我第一次成爲程序員,真的爲自己製作這樣一些愚蠢的設計而自責! – Chris 2011-03-04 14:58:59

+0

哈哈,我明白了。我們都會犯這樣的錯誤。有時候,我們可以騰出時間做出這樣的改變來幫助緩解災難,有時候最好的選擇就是簡單地接受它。我希望事情順利。 – FreeAsInBeer 2011-03-04 15:12:14

+0

我看到了這一點,我完全同意。可悲的是,許多人忽視了這樣的好建議,並且實際上允許這種非規範化的數據以XML鼓的形式存儲在表格中。 ;-) – 2012-02-25 22:30:59

相關問題