使用对列表高效地选择SQL server中的行?
我有一张相当大的桌子,有几百万行。我正在尝试编写一个高效的代码,该代码将选择在python代码中传递给它的成对列表中有两列值的行。一个合理的答案是 例如 返回的表通过使用对列表高效地选择SQL server中的行?,sql,sql-server,python-3.x,pandas,Sql,Sql Server,Python 3.x,Pandas,我有一张相当大的桌子,有几百万行。我正在尝试编写一个高效的代码,该代码将选择在python代码中传递给它的成对列表中有两列值的行。一个合理的答案是 例如 返回的表通过pd.read\u sql\u query放入数据帧。我这里有两个问题(除了一个是速度慢)。其中,id2可以是NULL,并且对这些行的查询失败。另一个更重要的问题是,where子句中元组列表的大小可能变化很大,从1到数百万不等 我的理解是,在大列表情况下,最好使用pandas将整个列导入python,然后在那里进行过滤。但是,我如何
pd.read\u sql\u query
放入数据帧。我这里有两个问题(除了一个是速度慢)。其中,id2
可以是NULL
,并且对这些行的查询失败。另一个更重要的问题是,where
子句中元组列表的大小可能变化很大,从1到数百万不等
我的理解是,在大列表情况下,最好使用pandas将整个列导入python,然后在那里进行过滤。但是,我如何使小列表和大列表之间的转换平稳?有没有一种方法可以通过SQLServer和Python的巧妙结合来实现呢 的
where
子句
convert(id1) + '-' + id2 in ('2261-7807403')
这不是最优的。我们可以很容易地看到,这里我们期望id1
为2261,id2
为7807403,因此最好使用where子句,如
where (id = '2261' and id2 = '7807403')
您可以执行类似于(…)或(…)或(…)等的where
子句。如果要允许id2
值为null
,可以
where (id = '2261' and isnull(id2, '7807403') = '7807403')
如果仍然存在性能问题,那么您可以考虑对这些列进行索引。
现在,我们还必须讨论一个迄今尚未解决的问题,即规模。你需要定义在你的案例中什么是大的。如果元素的数量很大,则将查询转换为CSV文件(或多个文件,如果需要)并使用Python加载。因此,为了避免在不合适的情况下加载大数据,您可以先选择count(*)并确定它是否大。您应该使用正确的类型传递值。一种方法是构造派生表并使用
join
:
select t.*
from table t join
(values (2261, 7807403), . . .
) v(id1, id2)
on t1.id1 = v.id1 and t.id2 = v.id2;
不应将值转换为字符串进行比较。这不仅是“荒谬的”,而且会严重影响绩效
对于NULL
s,除非您有特殊的逻辑,否则它们将不匹配。SQL没有空安全比较
select t.*
from table t join
(values (2261, 7807403), . . .
) v(id1, id2)
on (t1.id1 = v.id1 or t1.id1 is null and t2.id2 is null) and
(t.id2 = v.id2 or t1.id1 is null and t2.id2 is null);
请注意,这可能会影响执行计划。元素的数量可以在100万到100万之间变化。@guy12345您可以创建一个临时表。当值的数量很小时,我运行此查询没有任何问题,但当值的数量超过100时,它就会被卡住。有什么解决办法吗?我们是否需要为
v
表编制索引?@guy12345。t1(id2,id2)
上的索引将用于第一个查询。优化第二个更为棘手。我们如何设置该索引?为什么更棘手<代码>空不允许用于复合索引?@guy12345。SQL Server可能不会将索引用于支持NULL
所需的更复杂的比较。索引明确支持NULL
s;这不是问题所在。SQL Server没有NULL
-安全的比较运算符,不善于优化或s。
select t.*
from table t join
(values (2261, 7807403), . . .
) v(id1, id2)
on (t1.id1 = v.id1 or t1.id1 is null and t2.id2 is null) and
(t.id2 = v.id2 or t1.id1 is null and t2.id2 is null);