2013-03-12 96 views
1

請注意,我已經在系統下有這樣的改變它需要時間。因此,我所知道的最好的辦法是規範,但...SQL需要內部加入

我有followng 2個表

Tbl1 

CompId  CommaList 
------  -------- 
2   '122','54','90' 
54   '53','76' 
34   '87' 
22   '98' 


Tbl2 

ID  ClientId 
--  -------- 
1  122 
2  76 
3  87 
4  98 

我需要的是加入TBL1和TBL2,然後返回CompId和ID

聯接應從tbl2.ClientId做與tbl1.CommaList(這是從我需要找到一個匹配值逗號delimted列表。

希望這是有意義的。

select tbl1.CompId, tbl2.Id 
    from tbl1 join tbl2 on CommaList = tbl2.ClientId 

顯然這不會工作,因爲它們是不同的類型,我還需要在CommaList中找到列表。

最後的結果應該是這樣的:

ID  CompId 
--  ------ 
1  2 
2  54 
3  34 
4  22 
+1

您將需要反序列包含在TBL1的CommaList第一數據。 – 2013-03-12 16:22:04

+0

......這就是爲什麼你不應該使用多值列 – 2013-03-12 16:24:53

+1

對於每個CompId,ClientId,Tbl1應該有一行,而不是每個CompId都有一行,所有的客戶端都被塞進一個值。 – 2013-03-12 16:25:54

回答

3

免責聲明在數據庫中存儲列逗號分隔的列表是一個代碼氣味,通常表明你需要規範化的數據庫結構。請在您的代碼中儘可能地使用請勿


您可以通過LIKE子句中的逗號分隔的列表中的客戶端ID值匹配解決:

select 
    t2.ID, t1.CompId 
from Tbl1 t1 
join Tbl2 t2 on t1.CommaList 
    like '%''' + cast(t2.ClientId as varchar(10)) + '''%' 

演示:http://www.sqlfiddle.com/#!3/6d416/6

+1

要原始海報:請注意**免責聲明**。 – 2013-03-12 16:33:23

+1

需要正常化(不正常) – Paparazzi 2013-03-12 17:43:56

+0

@Blam:好點:)固定。 – mellamokb 2013-03-12 17:46:51

1

試試這個:

select tbl1.CompId, tbl2.Id 
from tbl1, tbl2 
where CHARINDEX('''' + CONVERT(varchar(50),tbl2.ClientId) + '''', CommaList)<> 0 
+1

你需要小心控制比賽的開始和結束 - 例如,通過加入單引號'''。否則,當一個clientId是另一個客戶端的子串時,此解決方案將打開以匹配誤報。例如,如果commaList包含「871」,則「87」的clientId將匹配:http://www.sqlfiddle.com/#!3/2ccc2/1 – mellamokb 2013-03-12 16:33:35

+0

已更正。感謝您的線索! – www 2013-03-12 16:43:14

2

幾乎可以肯定你想用aj來做到這一點oin表,擴展CommaList。也就是說,你想與

Tbl3 
CompID  ClientID 
2   122 
2    54 
2    90 
54   53 

表有些數據庫讓您存儲CommaList作爲數組並使用IN運營商,但是這兩個不標準,效率低下。 (你也可以做一個字符串搜索一樣mellamokb的答案,但注意到他的聲明是我的一樣。)現在,你可以做

SELECT id, compID FROM Tbl3 NATURAL JOIN Tbl2; 

除特殊情況外,應避免像Tbl1非規範化的數據。

+1

+1除外,SQL Server不支持'NATURAL JOIN'。 – mellamokb 2013-03-12 16:29:16

+1

鑑於mekkamokb評論,更正到 '''''''我知道有一個喜歡PostgreSQL的理由。 – 2013-03-12 16:32:00

2

我發佈了一個解決方案,我沒有測試過,但應該可以工作。感覺不對做的方式,我現在鼓勵你的答案感到不潔淨

SELECT tbl1.CompId, tbl2.Id 
FROM tbl1 
    JOIN tbl2 ON CommaList LIKE '%''' + CAST(tbl2.ClientId AS VARCHAR) + '%''' 
0

如果由於某種原因,你不能使用Char Indexlike解決方案,您可能分裂逗號名單,然後加入。例如,如果你需要做的

從tbl2的概念等同於CommaList = tbl2.ClientId LEFT加入TBL1加入

with split as (

SELECT 
     CompID, 
     Substring(commalist, number, Charindex(',', commalist + ',', number) 
            - number) 
                    AS clientID 
FROM tbl1 
     JOIN master..spt_values v 
     ON number <= Len(commalist) 
      AND Substring(',' + commalist, number, 1) = ',' 
WHERE v.type = 'P') 

SELECT 

    split.CompId, 
    split.clientID, 
    tbl2.id 


FROM 

    split 
    LEFT JOIN tbl2 
    on tbl2.clientID = split.clientID 

DEMO

注:

  • 我沒有打擾處理報價分隔部分,但你可以很容易地通過replace(commalist,'''','')
  • 原樣,這隻適用於長度爲< = 2047的commalist值。如果你正在處理較大的列表,你可以使用GarethD'sexample in this answer,以產生更大的數字表