【问题标题】:SQL query to get ids NOT in a tableSQL查询以获取不在表中的ID
【发布时间】:2012-01-29 15:03:36
【问题描述】:

给定一个 ID 列表,我需要确定那些不在 Oracle 数据库中的 ID。例如,给定表格:

my_table

+----+-------+
| ID | DATA  |
+----+-------+
|  1 | Foo   |
+----+-------+
|  3 | Bar   |
+------------+
|  5 | Etc   |
+------------+

...给定列表 [1, 2, 3, 4],我需要列表 [2, 4]。

我使用MINUS 子句提出了这种语法:

SELECT '1' as id FROM dual
UNION
SELECT '2' as id FROM dual
UNION
SELECT '3' as id FROM dual
UNION
SELECT '4' as id FROM dual
MINUS
SELECT id FROM my_table WHERE id IN ('1','2','3','4')

但这看起来很笨拙,很快就会变得一团糟,因为实际上我一次要处理数百个 ID。 有没有比 UNION 语法更好的语法来获取值列表?

大意是:

/* Pseudo code */
SELECT id FROM VALUES ('1', '2', '3', '4')
MINUS
SELECT id FROM my_table WHERE id IN ('1','2','3','4')

另一种选择是以编程方式进行。我可以在数据库中查询现有的 ID。然后在代码中,我可以删除从原始列表中找到的列表,以获取不在数据库中的子列表。这会起作用,但我认为让数据库完成这项工作会更有效吗?

谢谢

【问题讨论】:

  • 您是否在其他表上进行JOIN 并比较结果?您总是可以在这张桌子上做一个OUTER JOIN,对着另一个,然后在第二张桌子上测试哪些是Null
  • 不,很遗憾,加入将不起作用。我们有来自一个系统的 ID,需要确定哪些 ID 不在另一个系统中。 (完全不同的系统和数据库。)例如,我们有来自工资系统的员工 ID,需要找出哪些 ID 不在停车登记系统中。谢谢。
  • 加入会起作用。您可能只需要先进行一些设置,例如将“其他”ID 放入可以连接的自己的表中。
  • @wadesworld 谢谢。我想到了一个临时表。但我的印象是临时表是昂贵的操作。这是一个需要经常运行的查询。因此,根据我对 SQL 优化的有限知识,我认为编程解决方案会比使用临时表更有效。
  • @antisanity 他们在不同的服务器上。而且我们无权访问原始系统或数据库。 ID 是通过服务请求提交的。然后我们需要提取我们没有记录的 ID。

标签: sql oracle


【解决方案1】:

这个怎么样:

SELECT * FROM dual WHERE id NOT IN (SELECT id FROM my_table);

SELECT * FROM dual WHERE id NOT EXISTS (SELECT id FROM my_table);

【讨论】:

  • 这会导致错误:ORA-00904: "id": invalid identifier。我尝试了什么:SELECT * FROM dual WHERE id NOT IN (SELECT id FROM my_table WHERE id IN ('1', '2', '3', '4')) 我相信它不喜欢 where 子句中的标识符。可以从 dual 中选择有 WHERE 子句吗?即使是简单的查询SELECT 'xyz' as id FROM DUAL WHERE id IS NOT NULL 也会导致同样的错误。
  • 观看您的报价!你是说身份证吗?
  • 反引号是 SQL 标识符中的无效字符
【解决方案2】:

如此处所述:如何how-to-convert-csv-to-table-in-oracle 您可以将值列表转换为表格。

在这之后,事情就简单了:

select * from table(splitter('a,b,c,d'))
minus
select id from my_table;

select 
  column_value as id 
from table(splitter('a,b,c,d')) a
  left join my_table b on (a.column_value = b.id)
where b.id is null;

【讨论】:

  • 谢谢,效果很好。我曾搜索过这样的功能。猜猜我根本没有正确的关键字。感谢您的帮助。
【解决方案3】:

我没有方便的 Oracle 实例来测试并确保我的语法是完美的,但这应该可以工作,或者无论如何都能让你走上正轨。

将列表作为嵌套表传入,然后将其视为真实表。您将列表作为数组从 Java/Perl 或您用来调用存储过程的任何语言传入。

TYPE ID_ARRAY_T is TABLE of NUMBER;


PROCEDURE FIND_IDS_NOT_IN_LIST( i_list IN ID_ARRAY_T, o_output OUT SYS_REFCURSOR)
IS
v_id ID_ARRAY_T;
BEGIN
OPEN O_OUTPUT FOR
 SELECT column_value FROM TABLE(v_id) WHERE column_value 
   NOT IN (select ID from my_table);
END FIND_IDS_NOT_IN_LIST;

【讨论】:

  • 谢谢@wadesworld。我想我可以做到这一点。我能够按照您的描述创建程序。 (你的语法已经死了。)但我需要把它打包在晚上,因为它在我的时区 非常 晚了。我只需要在早上尝试从我的 java 代码中调用它。那我再跟进一些。再次感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-09
  • 1970-01-01
  • 1970-01-01
  • 2012-08-16
  • 2021-04-05
  • 2020-09-09
  • 2021-08-01
相关资源
最近更新 更多