将另一个表中的逐行值转换为字符串并将其插入到 SQL 中的 NOT IN 子句中

Posted

技术标签:

【中文标题】将另一个表中的逐行值转换为字符串并将其插入到 SQL 中的 NOT IN 子句中【英文标题】:Transform line-by-line values from another table to a string and insert it into NOT IN clause in SQL 【发布时间】:2020-12-27 04:03:39 【问题描述】:

我正在尝试使用 NOT IN 从“test_user”表中排除一系列测试用户。

我得到另一个包含用户 ID 和其他信息的“成员”表

本来tester用户表并不太长,所以大家使用NOT IN子句通过列出id来排除test用户,但是随着test用户一天天的增加,不知道有没有什么办法可以保留这个NOT IN () 是最新的并且易于维护。

我不确定是否有类似的解决方案:

@declare test_user varchar(23) = select ID from test_user

SELECT * FROM member WHERE ID NOT IN (@test_user)

感谢您的帮助!

【问题讨论】:

请不要使用图像作为数据,而是使用 DDL+DML 语句作为示例起始数据,并使用格式化文本以获得预期结果。 别想太多。除非性能过度下降,否则什么都不做。 感谢您的评论。当您提到“DDL+DML”语句时,您的意思是 CREATE TABLE table_name (....) 吗?对于预期的结果,你能分享一个例子吗?再次感谢! 创建一个临时表,并插入示例数据——这样人们就可以复制和粘贴进行测试。预期结果可以只是格式化的文本。作为创建minimal reproducible example 的一部分,您应该自己做这件事——在构建 MRE 时解决您自己的问题并不少见。这里是an example @DaleK 谢谢!以后我会效仿这个例子。此外,您的解决方案完美运行。非常感谢。 【参考方案1】:

您不需要该变量...只需将您的查询直接插入为not in 列表即可。

SELECT *
FROM member
WHERE ID NOT IN (SELECT ID FROM test_user);

注意:为您的查询使用一致的大小写和布局会更轻松。

【讨论】:

【参考方案2】:

你可以使用NOT EXISTS如下:

SELECT * FROM MEMBER M
WHERE NOT EXISTS 
  (SELECT 1 FROM TESTUSER T 
    WHERE T.ID = M.ID)

或者您可以使用LEFT JOIN,如下所示:

SELECT M.* 
  FROM MEMBER M LEFT JOIN TESTUSER T ON T.ID = M.ID
 WHERE T.ID IS NULL;

【讨论】:

LEFT JOIN WHERE NULL 的性能几乎总是低于直接反连接(您的第一选择)【参考方案3】:

你能修改member 表吗?如果是这样,您可以添加一个新列is_test_user。然后您可以使用查询

SELECT *
FROM member
WHERE is_test_user = 0

如果你这样做,我建议在is_test_user 上也添加一个索引。

编辑:由于问题已更新,我的答案不再适合。

编辑 2:根据 Bohemian 的建议删除了索引推荐。

【讨论】:

在布尔列上添加索引将无效,因为基数不足。但是,如果在 id 和 is_test_user 上都有覆盖索引,可能会有小幅性能提升。 嗨卡恩,很遗憾,我无法修改成员表。感谢您的回复! @Bohemian 感谢您的建议。我假设测试用户的数量将是一个很小的百分比,索引可能是有用的。这可能是正确的,也可能是不正确的。在任何情况下,OP 都不能修改成员表。 您仍然需要一种保持表格更新的方法,通常是触发器,这很容易使情况过于复杂。

以上是关于将另一个表中的逐行值转换为字符串并将其插入到 SQL 中的 NOT IN 子句中的主要内容,如果未能解决你的问题,请参考以下文章

如何将查询结果转换为字符串并将其插入表行

如何将字符串转换为时间并将其插入 MySQL

将谷歌电子表格行值转换为不同工作表中的列

计算表中的 2 列并将结果作为同一表中的其他列插入

将另一个表中的选定列插入表中[重复]

如何将 TIMESTAMP 转换为 VARCHAR 并将其保存到 Redshift 中的另一个表中?