(已编辑添加上下文信息)
我在表A中有2个字段,其中包含其他2个表中记录ID的CSV列表。 “USERS”字段包含USERS_TABLE中的CSV记录列表; “CONTACTS”字段包含CONTACTS_TABLE中的CSV记录列表:
USERS_FIELD:“1,2,3,4,5,6”
CONTACTS_FIELD:“2,4,6,8”
我想查找USERS_FIELD列表中但不在CONTACTS_FIELD列表中的所有记录。在这个例子中,我想要记录1,3,5。列表可以是1 ID到数百的任何位置。
解决方案必须在查询的WHERE子句中运行。我的环境是COTS产品中基于VBScript的脚本语言:在MS Windows Server和SQL Server 2012上运行的MicroFocus / Serena SBM。脚本语言允许我指定WHERE和ORDERBY子句,它执行查询并返回结果。将多个记录ID作为CSV存储在产品中。我无法做任何事情,也无法创建SQL临时表或定义SQL函数。主机脚本语言的实现删除了数组和“拆分”功能。虽然我可以将CSV解析为Dictionary对象,但迭代一对,每个都有几百个元素并不快。当最终用户正在等待网页完成时,这一切都在发生。同样,这就是产品的设计方式。
我可以使用UNION类型的运算符,并执行以下操作:
Select ID from USERS_TABLE Where ID in USERS_FIELD
MINUS
Select ID from CONTACTS_TABLE Where ID in CONTACTS_FIELD
不确定我是否遵循需要在WHERE子句中运行的解决方案的要求。如果您使用的是SQL Server 2017,则可以利用STRING_SPLIT(在SQL Server 2016中也可用)和STRING_AGG函数。
DROP TABLE IF EXISTS #A;
CREATE TABLE #A (id INT PRIMARY KEY IDENTITY, users VARCHAR(MAX), contacts VARCHAR(MAX));
INSERT INTO #A (users, contacts)
VALUES
('1,2,3,4,5,6', '2,4,6,8'),
('3,5,6', '4,6,9'),
('2,4,7,9', '2,4,9');
SELECT
A.id,
A.users,
A.contacts,
STRING_AGG(B.value, ',') intersection
FROM #A A
CROSS APPLY STRING_SPLIT(users, ',') B
WHERE NOT EXISTS (SELECT * FROM STRING_SPLIT(A.contacts, ',') X1 WHERE B.value = X1.value) -- where user is not in contacts
GROUP BY
A.id,
A.users,
A.contacts;