查找包含X和X_FOO列的表

时间:2015-11-06 17:41:34

标签: sql oracle

假设我有一些名为* _FOO:

的列的表
create table a(x number, x_foo number);
create table b(z_foo number);

如何查询USER_TAB_COLS以获取(a)包含X和X_FOO的列的列表,

select table_name, short_col, foo_col from ... user_tab_cols ...

TABLE_NAME  SHORT_COL FOO_COL
----------  --------- -------
A           X         X_FOO

和(b)没有相应X的X_FOO列表?

TABLE_NAME  FOO_COL
----------  -------
B           Z_FOO

这个问题是特定于Oracle的,因为查询会使用USER_TAB_COLS,但我认为查询连接将是通用SQL吗?

2 个答案:

答案 0 :(得分:2)

对于第一个基于连接的简单连接将执行:

select utc1.table_name, utc1.column_name, utc2.column_name
from user_tab_columns utc1
join user_tab_columns utc2
on utc2.table_name = utc1.table_name
and utc2.column_name = utc1.column_name || '_FOO';

TABLE_NAME                     COLUMN_NAME                    COLUMN_NAME                  
------------------------------ ------------------------------ ------------------------------
A                              X                              X_FOO                         

对于第二个,您可以从名为'%_FOO'的任何内容开始,并检查名称较短的列是否不存在:

select utc1.table_name, utc1.column_name
from user_tab_columns utc1
where utc1.column_name like '%\_FOO' escape '\'
and not exists (
  select null
  from user_tab_columns utc2
  where utc2.table_name = utc1.table_name
  and utc2.column_name = substr(utc1.column_name, 1, length(utc1.column_name) -4)
);

TABLE_NAME                     COLUMN_NAME                  
------------------------------ ------------------------------
B                              Z_FOO                         

如果您愿意,也可以使用外部联接:

select utc2.table_name, utc2.column_name
from user_tab_columns utc1
right outer join user_tab_columns utc2
on utc2.table_name = utc1.table_name
and utc2.column_name = utc1.column_name || '_FOO'
where utc2.column_name like '%\_FOO' escape '\'
and utc1.column_name is null;

TABLE_NAME                     COLUMN_NAME                  
------------------------------ ------------------------------
B                              Z_FOO                         

SQL Fiddle有两个外连接示例。

答案 1 :(得分:0)

你是否经历过这样的事情?

with sample_data as (select 'A' table_name, 'COL1' column_name from dual union all
                     select 'A' table_name, 'COL2' column_name from dual union all
                     select 'A' table_name, 'COL3' column_name from dual union all
                     select 'B' table_name, 'COL1' column_name from dual union all
                     select 'B' table_name, 'COL2' column_name from dual union all
                     select 'C' table_name, 'COL2' column_name from dual union all
                     select 'C' table_name, 'COL3' column_name from dual union all
                     select 'C' table_name, 'COL4' column_name from dual union all
                     select 'D' table_name, 'COL1' column_name from dual)
select distinct table_name,
                case when count(*) over (partition by table_name) = 2 then 'Both cols present'
                     when count(*) over (partition by table_name) = 1 and column_name = 'COL1' then 'COL1 present only'
                     when count(*) over (partition by table_name) = 1 and column_name = 'COL2' then 'COL2 present only'
                end cols_present
from   sample_data
where  column_name in ('COL1', 'COL2');


TABLE_NAME COLS_PRESENT     
---------- -----------------
A          Both cols present
B          Both cols present
C          COL2 present only
D          COL1 present only

也许是这样的:

with sample_data as (select 'A' table_name, 'COL1' column_name from dual union all
                     select 'A' table_name, 'COL2' column_name from dual union all
                     select 'A' table_name, 'COL3' column_name from dual union all
                     select 'B' table_name, 'COL1' column_name from dual union all
                     select 'B' table_name, 'COL2' column_name from dual union all
                     select 'C' table_name, 'COL2' column_name from dual union all
                     select 'C' table_name, 'COL3' column_name from dual union all
                     select 'C' table_name, 'COL4' column_name from dual union all
                     select 'D' table_name, 'COL1' column_name from dual)
select   table_name,
         max(case when column_name = 'COL1' then column_name end) first_col,
         max(case when column_name = 'COL2' then column_name end) first_col
from     sample_data
where    column_name in ('COL1', 'COL2')
group by table_name;

TABLE_NAME FIRST_COL FIRST_COL_1
---------- --------- -----------
A          COL1      COL2       
B          COL1      COL2       
C                    COL2
D          COL1         

(显然,我刚刚模拟了一个名为sample_data的子查询,其中包含一些数据;您只需直接查询user_tab_columns表。)