我有两张桌子:
EmployeeTypeA表
名称varchar(2000)字段包含 - 'john,sam,doug'
EmployeeTypeB表
名称varchar(2000)字段包含 - 'eric,sam,allen,stephanie'
使用MS SQL在两个列表中找到名称时,返回true或false的最有效方法是什么?这需要在存储过程中完成,因此我不能使用编程语言在SQL之外操作它。在这个例子中,因为'sam'在两个表中,我想要返回一个真(或0等)
我应该先将逗号分隔的字段分开,然后将这些项目放在临时表中吗?或者使用游标?
由于
答案 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