2013-03-12 99 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,以产生更大的数字表