sql >> データベース >  >> RDS >> Oracle

Oracle SQL-各列の個別のカウントを動的に取得するにはどうすればよいですか?

    列ごとに1つの結果セット行で問題がない場合は、この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() callは、その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() 関数はnullを無視するため、nullをカウントするには、nullを変換する必要があります。と

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

    ここに、2番目の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
    

    または、生成されたXMLから両方の列値を抽出する単一のXMLTableを使用して、両方のカウントを一度に実行するように変更します。

    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. 多くのデータを1つのデータとしてマージ

    2. where句でのOracleの日付比較

    3. 別の12cオプティマイザーホワイトペーパー

    4. doInbackground中に進行状況を表示する