我编写了一个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原因的限制?
答案 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
会更快,内存效率更高。
扩展他的回答我会建议采用以下方法:
JOIN
该表返回正确的记录对于第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));