[英]Oracle SQL - How to get distinct count for each column dynamically?
我发现的类似问题似乎并没有专门回答如何在不键入查询中每个列的情况下如何获取ALL列的不同元素的单独计数。
我想对所有列执行类似的操作,但不要在每一列中都输入:
SELECT
COUNT(distinct COL1) AS COL1DISTINCT,
COUNT(distinct COL2) AS COL2DISTINCT
FROM TABLE_NAME;
但是我们不想键入所有单独的列,因为需要在几个不同客户端上的其他几个表上检索相同的数据,所有这些表每次都具有不同的列名。
我试图找到一种访问列名以创建子查询的方法,但是我们的元数据表为空,不提供任何列名。
如果您同意每列一个结果集行,则可以采用以下XML魔术 :
select owner, table_name, column_name,
to_number(xmlquery('/ROWSET/ROW/C/text()'
passing xmltype(dbms_xmlgen.getxml(
'select count(distinct "' || column_name || '") as c '
|| 'from "' || owner || '"."' || table_name || '"'))
returning content)) as c
from all_tab_columns
where owner = '<your table owner>'
and data_type in ('NUMBER', 'DATE', 'TIMESTAMP', 'CHAR', 'VARCHAR2', 'NCHAR', 'NVARCHAR2');
...列出您需要能够计数的所有数据类型; 真的是排除那些不能处理distinct
像CLOB,但正如你可能已经嵌套表等,以及它可能会更简单列出那些你会想到可以算。
dbms_xmlgen()
调用将有效地动态构造的select count(distinct ...) ...
查询的结果转换为XML结构,然后您可以使用XMLQuery()
从中取出计数(代替链接答案中已弃用的extractvalue()
的值)。
作为一个非常快速的演示:
create table t42 (id number, str varchar2(20));
insert into t42 values (1, 'Test');
insert into t42 values (2, 'Test');
insert into t42 values (3, 'Test 2');
insert into t42 values (3, null);
select owner, table_name, column_name,
to_number(xmlquery('/ROWSET/ROW/C/text()'
passing xmltype(dbms_xmlgen.getxml(
'select count(distinct "' || column_name || '") as c '
|| 'from "' || owner || '"."' || table_name || '"'))
returning content)) as c
from all_tab_columns
where owner = 'MY_SCHEMA'
and table_name = 'T42'
and data_type in ('NUMBER', 'DATE', 'TIMESTAMP', 'CHAR', 'VARCHAR2', 'NCHAR', 'NVARCHAR2');
OWNER TABLE_NAME COLUMN_NAME C
--------------- --------------- --------------- ----------
MY_SCHEMA T42 ID 3
MY_SCHEMA T42 STR 2
有没有一种方法也可以在每列中获取空计数?
count()
函数会忽略空值,因此要计算这些值,您必须将其转换,例如
count(case when <your_column> is null then 1 end)
您可以在其中包含第二个XMLQuery子句:
select owner, table_name, column_name,
to_number(xmlquery('/ROWSET/ROW/C/text()'
passing xmltype(dbms_xmlgen.getxml(
'select count(distinct "' || column_name || '") as c '
|| 'from "' || owner || '"."' || table_name || '"'))
returning content)) as distinct_count,
to_number(xmlquery('/ROWSET/ROW/C/text()'
passing xmltype(dbms_xmlgen.getxml(
'select count(case when "' || column_name || '" is null then 1 end) as c '
|| 'from "' || owner || '"."' || table_name || '"'))
returning content)) as null_count
from all_tab_columns
where owner = 'MY_SCHEMA'
and table_name = 'T42'
and data_type in ('NUMBER', 'DATE', 'TIMESTAMP', 'CHAR', 'VARCHAR2',
'NCHAR', 'NVARCHAR2');
OWNER TABLE_NAME COLUMN_NAME DISTINCT_COUNT NULL_COUNT
--------------- --------------- --------------- -------------- ----------
MY_SCHEMA T42 ID 3 0
MY_SCHEMA T42 STR 2 1
或使用单个XMLTable从生成的XML中提取两个列值,并对其进行了修改以同时进行两个计数:
select a.owner, a.table_name, a.column_name,
x.distinct_count, x.null_count
from
(
select owner, table_name, column_name,
dbms_xmlgen.getxml(
'select count(distinct "' || column_name || '") as c1,'
|| 'count(case when "' || column_name || '" is null then 1 end) as c2 '
|| 'from "' || owner || '"."' || table_name || '"') as xml_clob
from all_tab_columns
where owner = 'MY_SCHEMA'
and table_name = 'T42'
and data_type in ('NUMBER', 'DATE', 'TIMESTAMP', 'CHAR', 'VARCHAR2',
'NCHAR', 'NVARCHAR2')
) a
cross join xmltable (
'/ROWSET/ROW'
passing xmltype(a.xml_clob)
columns distinct_count number path 'C1',
null_count number path 'C2'
) x;
OWNER TABLE_NAME COLUMN_NAME DISTINCT_COUNT NULL_COUNT
--------------- --------------- --------------- -------------- ----------
MY_SCHEMA T42 ID 3 0
MY_SCHEMA T42 STR 2 1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.