查询以在单个查询 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 上添加索引可能会有所帮助。
大家好,我遇到了一个要求,即找出特定架构 (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 上添加索引可能会有所帮助。