[英]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.