将值列表与表格进行比较
Posted
技术标签:
【中文标题】将值列表与表格进行比较【英文标题】:Comparing list of values against table 【发布时间】:2013-02-14 10:08:36 【问题描述】:我试图为这个问题找到解决方案一段时间但没有成功,所以任何帮助将不胜感激。需要将 ID 列表与表进行比较,并找出哪些记录存在(及其值之一),哪些不存在。 有一个ID列表,文本格式:
100,
200,
300
一个数据库表:
ID(PK) value01 value02 value03 .....
--------------------------------------
100 Ann
102 Bob
300 John
304 Marry
400 Jane
我需要的输出是:
100 Ann
200 missing or empty or whatever indication
300 John
明显的解决方案是创建表并加入,但我只有读取权限(数据库是封闭的供应商产品,我只是一个用户)。编写 PL/SQL 函数似乎也很复杂,因为表有 200 多列和 100k 多条记录,而我在创建动态记录数组时没有运气。此外,要检查的 ID 列表包含数百个 ID,我需要定期执行此操作,因此必须在单独的代码行中更改每个 ID 的任何解决方案都不会很有用。 数据库是Oracle 10g。
【问题讨论】:
【参考方案1】:有许多内置的公共集合类型。您可以像这样利用其中之一:
with ids as (select /*+ cardinality(a, 1) */ column_value id
from table(UTL_NLA_ARRAY_INT(100, 200, 300)) a
)
select ids.id, case when m.id is null then '**NO MATCH**' else m.value end value
from ids
left outer join my_table m
on m.id = ids.id;
要查看数据库上的公共类型列表,请运行:
select owner, type_name, coll_type, elem_type_name, upper_bound, precision, scale from all_coll_types
where elem_type_name in ('FLOAT', 'INTEGER', 'NUMBER', 'DOUBLE PRECISION')
提示
/*+ cardinality(a, 1) */
只是用来告诉 oracle 在我们的数组中有多少元素(如果没有指定,默认将假设 8k 元素)。只需设置一个相当准确的数字即可。
【讨论】:
【参考方案2】:您可以使用CONNECT BY
将变量转换为查询(在 11g 上测试,应该在 10g+ 上工作):
SQL> WITH DATA AS (SELECT '100,200,300' txt FROM dual)
2 SELECT regexp_substr(txt, '[^,]+', 1, LEVEL) item FROM DATA
3 CONNECT BY LEVEL <= length(txt) - length(REPLACE(txt, ',', '')) + 1;
ITEM
--------------------------------------------
100
200
300
然后您可以将此结果连接到表中,就像它是标准视图一样:
SQL> WITH DATA AS (SELECT '100,200,300' txt FROM dual)
2 SELECT v.id, dbt.value01
3 FROM dbt
4 RIGHT JOIN
5 (SELECT to_number(regexp_substr(txt, '[^,]+', 1, LEVEL)) ID
6 FROM DATA
7 CONNECT BY LEVEL <= length(txt) - length(REPLACE(txt, ',', '')) + 1) v
8 ON dbt.id = v.id;
ID VALUE01
---------- ----------
100 Ann
300 John
200
【讨论】:
【参考方案3】:解决此问题的一种方法是动态创建一个公共表表达式,然后可以将其包含在查询中。您的最终目标是:
with list_of_values as (
select 100 val from dual union all
select 200 val from dual union all
select 300 val from dual union all
...)
select
lov.val,
...
from
list_of_values lov left outer join
other_data t on (lov.val = t.val)
它不是很优雅,特别是对于大量值集,但与您可能没有多少权限的数据库的兼容性非常好。
【讨论】:
以上是关于将值列表与表格进行比较的主要内容,如果未能解决你的问题,请参考以下文章