如何克服sql查询中IN原因的限制

时间:2012-10-13 13:50:42

标签: sql sql-server oracle

我编写了一个sql查询,如:

select field1, field2 from table_name;

问题是此查询将返回100万条记录/或超过100条记录。 我有一个目录,其中包含field1的输入文件(大约20,000到50,000条记录)。这是我关注的主要数据。 使用perl脚本,我从目录中提取。 但是,如果我写一个像:

这样的查询
select field1 , field2 from table_name 
where field1 in (need to write a query to take field1 from directory);

如果我使用IN因为它有处理1000个条目的限制,那么我应该如何克服IN原因的限制?

4 个答案:

答案 0 :(得分:4)

在任何DBMS中,我都会将它们插入临时表并执行JOIN以解决列表大小的IN子句限制。

E.g。

CREATE TABLE #idList
(
    ID INT
)
INSERT INTO #idList VALUES(1)
INSERT INTO #idList VALUES(2)
INSERT INTO #idList VALUES(3)

SELECT * 
FROM 
    MyTable m 
    JOIN #idList AS t 
    ON m.id = t.id

在SQL Server 2005中,在我们之前的一个项目中,我们习惯将这个值列表转换为XML,并将其作为XML变量传递给XML查询并转换为XML的另一个数据存储(lucene索引)的结果使用XML数据类型上的nodes()函数将其放入表中,并使用JOIN执行该操作。

DECLARE @IdList XML
SELECT @idList = '
<Requests>
    <Request id="1" />
    <Request id="2" />
    <Request id="3" />
</Requests>'

SELECT * 
FROM 
    MyTable m 
    JOIN (
            SELECT id.value('(@id)[1]', 'INT') as 'id' 
            FROM @idList.nodes('/Requests/Request') as T(id)
         ) AS t 
    ON m.id = t.id

答案 1 :(得分:1)

Vikdor是对的,您不应该使用IN()子句来查询它,使用表格JOIN会更快,内存效率更高。

扩展他的回答我会建议采用以下方法:

  1. 通过Perl获取所有输入文件的列表
  2. 想想一些聪明的方法来计算列表的哈希值,该哈希值是唯一的并且基于所有输入文件(我建议使用文件名或类似名称)
  3. 此哈希将用作存储输入文件名的表的名称(将其视为准临时表,一旦哈希更改就会被丢弃)
  4. JOIN该表返回正确的记录
  5. 对于第2步,您可以在实际需要查询时使用cronjob或计算(但这会延迟响应)。要做到这一点,您需要考虑添加/删除文件的可能性。

    对于步骤3.如果当前哈希值与上次执行不同,则需要一些逻辑删除先前生成的表,然后重新创建以当前哈希命名的表。

    对于准临时表名,我建议使用

    input_files_XXX (.i.e. prefix_<hashvalue>)
    

    这使得更容易知道要删除的旧表。

答案 2 :(得分:0)

您可以在50个1000个ID列表中拆分50'000个ID,对每个这样的列表进行查询,并在perl中收集结果集。

答案 3 :(得分:0)

Oracle明智地说,使用临时表的最佳解决方案 - 没有索引不会给你带来太多性能就是使用嵌套的表格类型。

CREATE TYPE my_ntt是directory_rec;

的表

然后创建一个函数f1,它返回my_ntt类型的变量并在查询中使用。

从table_name中选择field1,field2,其中table1中的field1(cast(f1 as my_ntt));