SQL,试图摆脱大 IN 子句
Posted
技术标签:
【中文标题】SQL,试图摆脱大 IN 子句【英文标题】:SQL, trying to get rid of large IN cluase 【发布时间】:2015-11-23 03:43:10 【问题描述】:我有一张桌子,
Contacts:
Contact_ID (int)
ContactName (nvarchar)
我得到了一个可供选择的联系人 ID 列表。通常,我会这样做
SELECT *
FROM Contacts
WHERE IN (List of contact ID)
问题是,联系人 ID 列表可能会变得非常大,例如 50k 或更多。
所以我的问题是,有没有一种方法可以处理大量的联系人 ID 而无需使用 IN 子句?
编辑:我正在使用 Microsoft sql 服务器。查询和联系人 ID 在运行时构建并传递给 sqlCommand 类 (c#) 以执行。
【问题讨论】:
在两个表之间使用连接并允许 INNER 连接消除记录...使用相关子查询和 'exists' 子句(或类似的,取决于 RDBMS)(Exists 是 一般最快的其次是内部连接,其次是IN)那么什么RDBMS?表格中的联系人 ID 列表是否在某处? (不确定“给定联系人列表”是什么意思将“列表”插入临时表并使用存在或内部连接......但这有开销......你想要实现什么?只是提高了可读性? 您使用的是哪个 DBMS?每个优化器的行为都不同 不确定您使用的是哪个 DBMS,但大多数都允许您将这些 ID 放入临时表并加入临时表。那可能会更快。 SQLServer 自动将大型 IN 子句(>50 项左右)转换为 TempTable + EXISTS。更改对性能没有好处。 @xQbert 好像我的问题有点含糊,抱歉。我应该澄清查询是在运行时构建的,联系人 ID 列表也是如此。当我试图用一个大的 in 子句运行这个查询时,它 sql server 给了我一个“内部资源用完”的错误。 【参考方案1】:我会创建一个包含单列和聚集主键的表类型。
CREATE TYPE dbo.ContactId AS TABLE
(
ContactId INT NOT NULL PRIMARY KEY
);
使用表值参数将值传递到查询中。
将您的查询更改为
SELECT *
FROM Contacts
WHERE contactID IN (SELECT y.contactID FROM @yourtablevaluedparameter y)
OPTION (RECOMPILE)
OPTION (RECOMPILE)
用于获取考虑的行数,因为 50K 的最佳计划可能与 1 的不同。
You can find some example C# code for populating a TVP here
【讨论】:
创建另一个表可能是要走的路。我现在正在尝试这个解决方案。会让你知道!谢谢!【参考方案2】:如果你想要性能,我会使用 EXISTS 子句。
SELECT c.Contact_ID, c.ContactName
FROM Contacts c
WHERE EXISTS (List of contact ID)
【讨论】:
不清楚 OP 应该如何将其与“联系人 ID 列表”一起使用。IN
和 EXISTS
在 SQL Server 中给出相同的计划(不像 NOT IN
与 NOT EXISTS
)
抱歉,当我回答他时,他没有提供太多关于他的问题的信息。【参考方案3】:
创建一个临时表并以行的形式填充您的联系人 ID。 在您的表和临时表之间进行内部连接,如下所示。
SELECT c.*
FROM Contacts c
join #temptable t
on c.id=t.id
如果您在临时表的 Join 列上引入索引,那么您的查询会更快。
【讨论】:
以上是关于SQL,试图摆脱大 IN 子句的主要内容,如果未能解决你的问题,请参考以下文章
linqpad - 大 NOT IN 子句超出限制 - 还有其他方式吗? - Linq to SQL