2

我写了一个 sql 查询,如:

select field1, field2 from table_name;

问题是此查询将返回 100 万条记录/或超过 100k 条记录。我有一个目录,其中有包含 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

4 回答 4

4

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

例如

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 中,在我们之前的一个项目中,我们曾经将这个作为查询另一个数据存储(lucene 索引)结果的值列表转换为 XML,并将其作为 XML 变量在 SQL 查询中传递,并将其转换为表使用nodes()XML 数据类型上的函数并使用该函数执行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
于 2012-10-13T13:55:00.933 回答
1

Vikdor 是对的,您不应该使用IN()子句来查询它,使用表来JOIN.

扩展他的答案,我会推荐以下方法:

  1. 通过 Perl 获取所有输入文件的列表
  2. 想一些聪明的方法来计算你的列表的哈希值,它是唯一的并且基于所有输入文件(我推荐文件名或类似文件)
  3. 此哈希将用作存储输入文件名的表的名称(将其视为一个准临时表,一旦哈希更改就会被丢弃)
  4. JOIN该表返回正确的记录

对于第 2 步,您可以在实际需要查询时使用 cronjob 或计算(但这会延迟响应)。要做到这一点,您需要考虑添加/删除文件的可能性。

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

对于准临时表名称,我会推荐一些类似的东西

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

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

于 2012-10-13T14:17:50.763 回答
0

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

CREATE TYPE my_ntt 是 directory_rec 的表;

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

select field1 , field2 from table_name where field1 in table (cast (f1 as my_ntt));

于 2012-10-13T15:52:35.330 回答
0

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

于 2012-10-13T14:16:05.653 回答