Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Oracle SQL - Bagaimana cara mendapatkan jumlah yang berbeda untuk setiap kolom secara dinamis?

Jika Anda setuju dengan satu baris hasil-set per kolom, Anda dapat menyesuaikan trik sulap XML ini :

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');

... daftar semua tipe data yang Anda butuhkan untuk dapat menghitung; sebenarnya itu untuk mengecualikan yang tidak dapat menangani distinct seperti CLOB, tetapi karena Anda mungkin memiliki tabel bersarang dll., mungkin akan lebih mudah untuk membuat daftar yang Anda lakukan ingin dan berharap bisa berhitung.

dbms_xmlgen() panggilan mengonversi hasil dari select count(distinct ...) ... kueri, yang secara efektif dibangun secara dinamis, ke dalam struktur XML, dan Anda kemudian dapat menghitungnya dengan XMLQuery() (sebagai ganti extractvalue() yang sudah tidak digunakan lagi dalam jawaban tertaut).

Sebagai demo yang sangat cepat:

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() fungsi mengabaikan nol, jadi untuk menghitungnya Anda harus mengonversinya, mis. dengan

count(case when <your_column> is null then 1 end)

Anda dapat menyertakannya di sini dengan klausa XMLQuery kedua:

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

atau dengan XMLTable tunggal yang mengekstrak kedua nilai kolom dari XML yang dihasilkan, yang dimodifikasi untuk melakukan kedua penghitungan sekaligus:

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



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara menginstal ODP.NET 2.111 dan ODP.NET 4.112 di mesin yang sama secara berdampingan sementara keduanya menunjuk ke server database yang sama

  2. GROUP BY / kebingungan fungsi agregat dalam SQL

  3. ORA-00922:opsi hilang atau tidak valid saat mengeksekusi pernyataan 100000 yang panjang di Oracle

  4. Hasilkan Prosedur PL/SQL Online untuk Mengimpor Data di Tabel Oracle

  5. Bagaimana cara memformat pencetakan SQL Query dengan cantik di SQLAlchemy?