2015-11-06 1 views
2

Пусть у меня есть таблицы со столбцами по имени * _foo:найти таблицу со столбцами X и X_FOO

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

Как я могу запросить USER_TAB_COLS получить (а) список столбцов, где одновременно 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_FOO, у которого нет соответствующего X?

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

Этот вопрос является Oracle конкретного в том, что запрос будет использовать USER_TAB_COLS, но я думаю, что запрос будет присоединиться к общим SQL?

+0

Чтобы уточнить, вы ищете любые таблицы с столбцами со связанными именами X и X_FOO, где X может быть любым и FOO фиксировано; и не зная, какой X вы ищете? –

+0

правильный. Я уточню вопрос, чтобы это изложить. –

ответ

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 непосредственно.)

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 с двумя примерами внешнего соединения.

Смежные вопросы