2012-12-13 48 views
1

我知道有过类似主题的一些讨论,但这次不同了一下甲骨文 - 每列的不同值

我需要在Oracle中的查询来获取值对(列名,重复值的计数)给定的表格。

例如:来回此表

| ID  | NAME | AGE | 
____________________________________ 
| 01  | MARY | 10 | 
| 02  | MAX  | 30 | 
| 03  | ALICE | 30 | 
| 04  | MARY | 20 | 
| 05  | JOE  | 10 | 
____________________________________ 

我需要得到

| COLUNL | DIST. VALUES | 
________________________________ 
| ID  | 5  | 
| NAME | 4  | 
| AGE | 3  | 
________________________________ 

的问题是,我不知道该表的结构。我将只有表名,我需要为它们中的每一个生成这些信息。 任何想法?????

+1

你想要生成dinamicaly的列名? –

+0

我认为你的第5行的ID 04应该是05. –

+0

是的,我需要它们产生dinamicaly – user1900474

回答

6

每列中不同值的数目被存储在系统表USER_TAB_COL_STATISTICS。通过调用程序DBMS_STATS.GATHER_TABLE_STATS收集统计数据。问问你的DBA,它应该已经建立起来了。

CREATE TABLE mytable (id NUMBER, name VARCHAR2(10), age NUMBER); 
INSERT INTO mytable VALUES (01, 'MARY', 10); 
INSERT INTO mytable VALUES (02, 'MAX', 30); 
INSERT INTO mytable VALUES (03, 'ALICE', 30); 
INSERT INTO mytable VALUES (04, 'MARY', 20); 
INSERT INTO mytable VALUES (04, 'JOE', 10); 
COMMIT; 
EXECUTE dbms_stats.gather_table_stats(user, 'MYTABLE'); 

SELECT table_name, column_name, num_distinct 
    FROM user_tab_col_statistics 
WHERE table_name = 'MYTABLE'; 

TABLE_NAME COLUMN_NAME NUM_DISTINCT 
MYTABLE ID   4 
MYTABLE NAME  4 
MYTABLE AGE   3 
0

您可以使用UNION,如做到这一点...

SELECT 'ID', Count(Distinct ID) As ValueCount From TableName 
UNION 
SELECT 'NAME', Count(Distinct NAME) From TableName 
UNION 
SELECT 'AGE', Count(Distinct AGE) From TableName 

[编辑]
另一种方法是分析表中,如...

ANALYZE TABLE TABLENAME COMPUTE STATISTICS; 

然后...

SELECT COLUMN_NAME, NUM_DISTINCT FROM USER_TAB_COLUMNS WHERE TABLE_NAME = 'TABLENAME' 
+0

对不起,lynamc,我忘记提及我想要做到这一点,而不知道表的结构。我所有的将会是表格名称。 – user1900474

+0

啊。那么你可以问Oracle。请参阅上述编辑。如果它是一张大桌子,并且您想要做很多事情,这不是非常实用。 –

+0

@Ciarán:特别是对于大型表格,为优化器提供良好的统计信息是非常实用的。但是'ANALYZE TABLE'为此目的已经过时,应该使用'DBMS_STATS'来代替。 –

0

您可以使用UNION ALL查询UNPIVOT再算上数据:

select col col_name, 
    count(distinct value) 
from 
(
    select cast(id as varchar(10)) value, 'id' col 
    from yourtable 
    union all 
    select name value, 'name' col 
    from yourtable 
    union all 
    select cast(age as varchar(10)) value, 'age' col 
    from yourtable 
) 
group by col 

SQL Fiddle with Demo

如果您正在使用Oracle 11g +,那么你可以使用UNPIVOT函数来执行此:

select col, count(distinct value) CountofValue 
from 
(
    select cast(id as varchar(10)) id, 
    name, 
    cast(age as varchar(10)) age 
    from yourtable 
) 
unpivot 
(
    value 
    for col in (id, name, age) 
) 
group by col 

SQL Fiddle with Demo

+0

对不起bluefeet,我忘记提及我不想知道桌子的结构。我所有的将会是表格名称。 – user1900474

0

下面的ideea,你应该对它有点工作:

create table stats_on_tables(
    date_id date, 
    table_name varchar2(32), 
    col_name varchar2(32), 
    cnt_distinct number 
); 

,然后创建与参数p_table_name一个过程是:

for n in (select column_name from user_tab_columns where table_name = p_table_name) 
loop 
    execute immediate 
    'insert into stats_on_table (date_id, table_name, col_name, cnt_distinct) 
    values (sysdate, '||p_table_name||','||n.column_name||', (
    select count(distinct '||n.column_name||') from '||p_table_name||'))'; 
end loop; 
commit; 
+0

谢谢!非常有用,当你没有时间/空间/权限来生成统计信息:) – user1900474