搜索逗号分隔字段中两个不同表之间是否存在字符串字

时间:2009-11-19 21:04:52

标签: sql sql-server tsql

我有两张桌子:

EmployeeTypeA表
名称varchar(2000)字段包含 - 'john,sam,doug'

EmployeeTypeB表
名称varchar(2000)字段包含 - 'eric,sam,allen,stephanie'

使用MS SQL在两个列表中找到名称时,返回true或false的最有效方法是什么?这需要在存储过程中完成,因此我不能使用编程语言在SQL之外操作它。在这个例子中,因为'sam'在两个表中,我想要返回一个真(或0等)

我应该先将逗号分隔的字段分开,然后将这些项目放在临时表中吗?或者使用游标?

由于

6 个答案:

答案 0 :(得分:2)

首先将逗号分隔的字段分隔为临时表或表变量。这样,您就可以准确地加入或匹配行。为每个名称添加一行,并包含一些可帮助您关联行的键列。

执行此操作的最佳方法是使用“帮助程序表”,如下所示:

DECLARE @numbers TABLE (number int)
DECLARE @i int 
SET @i = 1
WHILE (@i < 1001)
BEGIN    
INSERT INTO @numbers (number) VALUES (@i)    
SET @i = @i+1
END


DECLARE @TestString VARCHAR(200)
SET @TestString = 'andy,john,mark'
DECLARE @RowDelimiter VARCHAR(1)
SET @RowDelimiter=','

SELECT SUBSTRING(@TestString+@RowDelimiter, number, 
    CHARINDEX(@RowDelimiter, @TestString+@RowDelimiter, number) - number) 
FROM @numbers 
WHERE number <= LEN(@TestString) 
AND SUBSTRING(@RowDelimiter+ @TestString, number, 1) = @RowDelimiter
ORDER BY number 
-- helper table technique: bill@creaticle.com

结果是:

andy
john
mark

一旦有了两个临时表,然后执行FULL OUTER JOIN并将“找到两者”列中包含设定值。您将获得两者中未找到的名称的NULL值 - 您可以将NULL视为“False”值。

你能提一下为什么你需要为两个表之间的匹配得到一个布尔值吗?接下来你打算用它做什么?有时解释这将导致更好的解决方案。您可能会发现您正在匆忙做出假设。最好,比尔。

答案 1 :(得分:1)

未测试:

SELECT COUNT(*) FROM EmployeeTypeA 
 WHERE ',' + nameListField + ',' LIKE '%,' + @searchedName + ',%'
如果在第一个表的一个列表中找到了名称,

应该返回一些值> 0。对第二个表执行相同操作,如果两个SELECT都返回非零值,则返回true。

PS:如果您有权更改数据库设计:执行此操作。规范化数据库不应包含以逗号分隔的列表,而应包含具有外键关系的子表。

答案 2 :(得分:1)

这是一个创建两个测试表的脚本,如果名称在两个表中,则返回名称列表,其中包含“True”。它通过使用左连接来查找两个表中或仅在表A中的名称。此结果集联合到右连接以获取仅在表B中的名称。

DROP TABLE EmployeeTypeA
DROP TABLE EmployeeTypeB
GO

CREATE TABLE EmployeeTypeA
    (Name VARCHAR(2000))
GO

CREATE TABLE EmployeeTypeB
    (Name VARCHAR(2000))
GO

INSERT INTO EmployeeTypeA VALUES ('john')
INSERT INTO EmployeeTypeA VALUES ('sam')
INSERT INTO EmployeeTypeA VALUES ('doug')

INSERT INTO EmployeeTypeB VALUES ('eric')
INSERT INTO EmployeeTypeB VALUES ('sam')
INSERT INTO EmployeeTypeB VALUES ('allen')
INSERT INTO EmployeeTypeB VALUES ('stephanie')
GO

SELECT
    eta.Name,
    CASE
        WHEN etb.Name IS NULL THEN 'False'
        ELSE 'True'
    END
FROM
    EmployeeTypeA eta
    LEFT JOIN EmployeeTypeB etb ON
        eta.Name = etb.Name

UNION

SELECT
    etb.Name,
    'False'
FROM
    EmployeeTypeA eta
    RIGHT JOIN EmployeeTypeB etb ON
        eta.Name = etb.Name
WHERE
    eta.Name IS NULL

GO

答案 3 :(得分:0)

这是我上面的第2部分,所以我可以添加其他代码。这部分解释了如何在将名称翻录成单独的行之后获取表格之间是否匹配的布尔值。

DECLARE @LeftTable TABLE (thisid int, thisname varchar(50))

INSERT INTO @LeftTable VALUES  (1, 'andy')
INSERT INTO @LeftTable VALUES  (2, 'bill')
INSERT INTO @LeftTable VALUES  (3, 'zed')

DECLARE @RightTable TABLE (thisid int, thisname varchar(50))

INSERT INTO @RightTable VALUES  (1, 'chris')
INSERT INTO @RightTable VALUES  (2, 'bill')
INSERT INTO @RightTable VALUES  (3, 'zed')

SELECT 
a.thisname AS theleftname, 
b.thisname AS therightname, 
CASE
    WHEN (ISNULL(a.thisname,'') = '' OR ISNULL(b.thisname,'') = '') THEN 'False'
    ELSE 'True'
END     
AS namematches
FROM @LeftTable a
FULL OUTER JOIN @RightTable b
ON a.thisname = b.thisname
-- www.caliberwebgroup.com

结果如下:

theleftname therightname    namematches 
NULL    chris   False
bill    bill    True
zed     zed     True
andy    NULL    False

答案 4 :(得分:0)

你可以编写一个表值函数,它接受一个逗号分隔的字符串并返回一个字符串的表(一列)。

Create FUNCTION [dbo].[SplitStrings]
(
    @StringList varchar(max)
)
RETURNS 
@Outputable table
(
    ParsedItem varchar(2000)
)

as

-- you can have a while loop here to populate the table.

这也将使您的代码可以恢复。 但是请记住,如果你使用很多行,这可能是一个性能瓶颈。它会在每一行都运行。

更新!!!

是的,当你拿到桌子时,你可以使用其他答案的连接。

答案 5 :(得分:0)

试试这个

declare @EmployeeTypeA table(Name VARCHAR(2000))
insert into @EmployeeTypeA select 'john,sam,doug'
declare @EmployeeTypeB table(Name VARCHAR(2000))
insert into @EmployeeTypeB select  'eric,sam,allen,stephanie'

- 计划开始

declare @xA xml
declare @xB xml
select @xA = '<i>' + REPLACE(Name, ',', '</i><i>') + '</i>'  from @EmployeeTypeA
select @xB = '<i>' + REPLACE(Name, ',', '</i><i>') + '</i>'  from @EmployeeTypeB

select 
 EmployeeTypeA
 ,EmployeeTypeB     

from (
SELECT 
  EmployeeTypeA
  ,i.value('.', 'VARCHAR(MAX)') EmployeeTypeB
  FROM @xB.nodes('//i') x(i)
  cross apply(
  SELECT i.value('.', 'VARCHAR(MAX)') EmployeeTypeA
  FROM @xA.nodes('//i') x(i)) Y) Res(EmployeeTypeA,EmployeeTypeB)
  where EmployeeTypeA = EmployeeTypeB

输出:

EmployeeTypeA EmployeeTypeB

sam             sam