查询以在单个查询 oracle 中查找各种组合搜索和计数

query to find various combinations search and counts in single query oracle

大家好,我遇到了一个要求,即找出特定架构 (SCHEMA_A) 中列 (col1、col2、col3) 的计数,但这是我必须找出的问题所有列的组合以获得使用 VALID_FROM_DATE、VALID_FROM_DATE、TIMESTAMP 的计数,下面是更多详细信息

数据库 - Oracle 11g

Table 正在搜索 - DBA_TAB_COLUMNS

col1 - VALID_FROM_DATE

col2 - VALID_TO_DATE

col3 - 时间戳

组合搜索以及所有表格中的计数

combination 1 
VALID_FROM_DATE + VALID_TO_DATE + TIMESTAMP

combination 2
VALID_FROM_DATE + VALID_TO_DATE 

combination 3 
VALID_FROM_DATE + TIMESTAMP

combination 4 
VALID_TO_DATE + TIMESTAMP

combination 5 
VALID_FROM_DATE

combination 6 
VALID_TO_DATE

combination 7 
TIMESTAMP

查询 - 我正在尝试

select count(distinct table_name) from DBA_TAB_COLUMNS
where owner='SCHEMA_A'
and column_name in ('VALID_FROM_DATE','VALID_TO_DATE','TIMESTAMP')
order by table_name;

但是如何在单个查询中实现上述组合 (1-7) 以捕获计数以及总体百分比,是否有可能以最简单的方式实现一个查询块

percentage - round(100*ratio_to_report(count(*)) over (), 2) percentage

有什么建议吗?

我想你正在寻找这样的东西。我正在使用多个 CTE 分步拆分逻辑

  • x_dba_tab_columns cte 只是模拟的测试数据dba_tab_columns
  • all_tables cte 是 tables
  • 的不同列表
  • table_w_cols cte 将每个 table 连接到 x_dba_tab_columns 过滤列,returns 如果列存在则为 1,如果不存在则为 0

最后的select只是一个计算组合的case语句

with x_dba_tab_columns (table_name, column_name)
AS
(
  SELECT 'TABLE1','VALID_FROM_DATE' FROM DUAL UNION ALL
  SELECT 'TABLE1','VALID_TO_DATE' FROM DUAL UNION ALL
  SELECT 'TABLE1','TIMESTAMP' FROM DUAL UNION ALL
  SELECT 'TABLE2','VALID_TO_DATE' FROM DUAL
  
), all_tables (table_name)
AS
(
  SELECT DISTINCT table_name FROM x_dba_tab_columns
), table_w_cols (table_name, vfd, vtd, ts)
AS
(
SELECT 
  t.table_name, 
  NVL2(vfd.table_name,1,0) vfd,
  NVL2(vtd.table_name,1,0) vtd,
  NVL2(ts.table_name,1,0) ts
  FROM all_tables t 
       LEFT OUTER JOIN x_dba_tab_columns vfd ON vfd.table_name = t.table_name AND vfd.column_name = 'VALID_FROM_DATE'
       LEFT OUTER JOIN x_dba_tab_columns vtd ON vtd.table_name = t.table_name AND vtd.column_name = 'VALID_TO_DATE'  
       LEFT OUTER JOIN x_dba_tab_columns ts ON ts.table_name = t.table_name AND ts.column_name = 'TIMESTAMP'  
)
SELECT 
  table_name,
  CASE 
    WHEN (vfd = 1 AND vtd = 1 AND ts = 1) THEN 'combination 1'
    WHEN (vfd = 1 AND vtd = 1) THEN 'combination 2'
    WHEN (vfd = 1 AND ts = 1) THEN 'combination 3'
    WHEN (vtd = 1 AND ts = 1) THEN 'combination 4'
    WHEN (vfd = 1) THEN 'combination 5'
    WHEN (ts = 1) THEN 'combination 7'
    WHEN (vtd = 1) THEN 'combination 6'
  END as combination 
FROM table_w_cols;

TABLE1  combination 1
TABLE2  combination 6

我相信完全外部联接在这里会起作用。

此处的子查询用于查找具有该列的表,然后将结果连接起来为我们提供所有可能的组合。

在最后一步计算组合。

select case when vfd.table_name is not null then 'VALID_FROM_DATE' else null end VALID_FROM_DATE, 
       case when vtd.table_name is not null then 'VALID_TO_DATE' else null end VALID_TO_DATE, 
       case when ts.table_name  is not null then 'TIMESTAMP' else null end TIMESTAMP_col,
       count(1) tables_cnt
  from            (select table_name from dba_tab_cols where column_name = 'VALID_FROM_DATE') vfd -- tables with 'VALID_FROM'
  full outer join (select table_name from dba_tab_cols where column_name = 'VALID_TO_DATE') vtd   -- tables with 'VALID_TO'
    on vfd.table_name = vtd.table_name
  full outer join (select table_name from dba_tab_cols where column_name = 'TIMESTAMP') ts        -- tables with 'TIMESTAMP'
    on vfd.table_name = ts.table_name
 where vfd.table_name is not null 
    or vtd.table_name is not null
    or ts.table_name is not null
 group by case when vfd.table_name is not null then 'VALID_FROM_DATE' else null end, 
          case when vtd.table_name is not null then 'VALID_TO_DATE' else null end, 
          case when ts.table_name  is not null then 'TIMESTAMP' else null end

我在这里使用的子查询只是为了提高可读性。万一有人骂你这里子查询错了,你可以用下面的版本

select case when vfd.table_name is not null then 'VALID_FROM_DATE' else null end VALID_FROM_DATE, 
       case when vtd.table_name is not null then 'VALID_TO_DATE' else null end VALID_TO_DATE, 
       case when ts.table_name  is not null then 'TIMESTAMP' else null end TIMESTAMP_col,
       count(1) tables_cnt
  from user_tab_cols vfd -- tables with 'VALID_FROM'
  full outer join user_tab_cols vtd   -- tables with 'VALID_TO'
    on vfd.table_name = vtd.table_name
    and vfd.column_name = 'VALID_FROM_DATE'
    and vtd.column_name = 'VALID_TO_DATE'
  full outer join user_tab_cols ts        -- tables with 'TIMESTAMP'
    on vfd.table_name = ts.table_name
    and vfd.column_name = 'VALID_FROM_DATE'
    and ts.column_name = 'TIMESTAMP'
 where vfd.column_name = 'VALID_FROM_DATE' 
    or vtd.column_name = 'VALID_TO_DATE' 
    or ts.column_name = 'TIMESTAMP'
 group by case when vfd.table_name is not null then 'VALID_FROM_DATE' else null end, 
          case when vtd.table_name is not null then 'VALID_TO_DATE' else null end, 
          case when ts.table_name  is not null then 'TIMESTAMP' else null end;

如果出现性能问题,在 dba_tab_cols 的 column_name 上添加索引可能会有所帮助。