如何 select 包含最大数量的不同值的列名? - 甲骨文 SQL
How to select the column name that contains maximum number of distinct values? - Oracle SQL
这是我当前的查询:
SELECT c.COLUMN_NAME, t.NUM_ROWS
FROM ALL_TAB_COLUMNS c
INNER JOIN ALL_TABLES t ON t.OWNER = c.OWNER AND t.TABLE_NAME = c.TABLE_NAME
WHERE c.TABLE_NAME='MY_TABLE_NAME'
AND c.OWNER = 'MY_SCHEMA_NAME'
这样做是检索我的 table 中每一列的名称以及每一列中的行数。
我需要做的是检索每列中存在的不同值的数量,然后最终确定哪一列具有最大数量的不同条目。鉴于我当前的查询,我将如何去做?
有没有更好的方法来实现我想做的事情?是否需要动态 SQL?
您可以使用 XMLQUERY
获取所需的结果。
Oracle 数据设置:
SQL> CREATE TABLE TEST_SO (COL1 NUMBER, COL2 VARCHAR(20));
Table created.
SQL>
SQL> INSERT INTO TEST_SO (COL1,COL2) VALUES (1, 'TEJASH');
1 row created.
SQL> INSERT INTO TEST_SO (COL1,COL2) VALUES (2, 'TEJASH1');
1 row created.
SQL> INSERT INTO TEST_SO (COL1,COL2) VALUES (3, 'TEJASH2');
1 row created.
SQL> INSERT INTO TEST_SO (COL1,COL2) VALUES (2, 'TEJASH3');
1 row created.
SQL> INSERT INTO TEST_SO (COL1,COL2) VALUES (2, 'TEJASH');
1 row created.
SQL>
现在,COL2
有 4 个不同的值,COL1
有 3 个不同的值。
使用以下查询获取 COL2
和 4(因为它大于 3(COL1
中的不同值))作为其中的不同值。
您的查询:
SQL> SELECT
2 C.COLUMN_NAME,
3 TO_NUMBER(XMLQUERY('/ROWSET/ROW/C/text()'
4 PASSING XMLTYPE(DBMS_XMLGEN.GETXML(
5 'select count(distinct "'
6 || C.COLUMN_NAME
7 || '") as c '
8 || 'from "'
9 || C.TABLE_NAME
10 || '"')) RETURNING CONTENT)) AS DISTINCT_VALS
11 FROM USER_TAB_COLUMNS C
12 WHERE C.TABLE_NAME = 'TEST_SO'
13 ORDER BY DISTINCT_VALS DESC NULLS LAST
14 FETCH FIRST ROW WITH TIES;
COLUMN_NAME DISTINCT_VALS
--------------- -------------
COL2 4
SQL>
干杯!!
自
- 您已准备好使用来自 all_% 视图的 num_rows 和
- 如果您收集了统计数据并且
- 一些可能的差异是acceptable,您可能会使用从all_tab_col_statistics收集的统计数据数据库。
像这样。
select num_distinct, column_name
from all_tab_col_statistics
where table_name = 'TABLE_NAME_UPPERCASE'
order by num_distinct desc
fetch first row with ties;
再次强调,当接受一些公差时请使用这个table。
尽管通常会定期收集 table 统计数据(取决于 DBA),但收集的值与实际值之间可能存在差距。
对于单个 table 你也可以这样的过程:
DECLARE
CURSOR Cols IS
SELECT COLUMN_NAME
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME = 'MY_TABLE_NAME'
ORDER BY COLUMN_ID;
cur INTEGER := DBMS_SQL.OPEN_CURSOR;
columnCount INTEGER := 0;
describeColumns DBMS_SQL.DESC_TAB2;
res INTEGER;
distinctValues NUMBER;
m NUMBER := -1;
c INTEGER := 0;
sqlstr VARCHAR2(30000);
BEGIN
FOR aCol IN Cols LOOP
sqlstr := sqlstr || ',COUNT(DISTINCT '||aCol.COLUMN_NAME||') AS '||aCol.COLUMN_NAME;
END LOOP;
sqlstr := REGEXP_REPLACE(sqlstr, '^,', 'SELECT ')||' FROM MY_TABLE_NAME';
DBMS_SQL.PARSE(cur, sqlStr, DBMS_SQL.NATIVE);
DBMS_SQL.DESCRIBE_COLUMNS2(cur, columnCount, describeColumns);
FOR i IN 1..columnCount LOOP
DBMS_SQL.DEFINE_COLUMN(cur, i, distinctValues);
END LOOP;
res := DBMS_SQL.EXECUTE(cur);
res := DBMS_SQL.FETCH_ROWS(cur); -- no loop required as you get always exactly one row
FOR i IN 1..columnCount LOOP
DBMS_SQL.COLUMN_VALUE(cur, i, distinctValues);
IF distinctValues > m THEN
m := distinctValues;
c := i;
END IF;
DBMS_OUTPUT.PUT_LINE ( describeColumns(i).col_name ||': '|| distinctValues );
END LOOP;
DBMS_OUTPUT.PUT_LINE ( 'Max distinct values at '||describeColumns(c).col_name ||': '|| m );
END;
这是我当前的查询:
SELECT c.COLUMN_NAME, t.NUM_ROWS
FROM ALL_TAB_COLUMNS c
INNER JOIN ALL_TABLES t ON t.OWNER = c.OWNER AND t.TABLE_NAME = c.TABLE_NAME
WHERE c.TABLE_NAME='MY_TABLE_NAME'
AND c.OWNER = 'MY_SCHEMA_NAME'
这样做是检索我的 table 中每一列的名称以及每一列中的行数。
我需要做的是检索每列中存在的不同值的数量,然后最终确定哪一列具有最大数量的不同条目。鉴于我当前的查询,我将如何去做?
有没有更好的方法来实现我想做的事情?是否需要动态 SQL?
您可以使用 XMLQUERY
获取所需的结果。
Oracle 数据设置:
SQL> CREATE TABLE TEST_SO (COL1 NUMBER, COL2 VARCHAR(20)); Table created. SQL> SQL> INSERT INTO TEST_SO (COL1,COL2) VALUES (1, 'TEJASH'); 1 row created. SQL> INSERT INTO TEST_SO (COL1,COL2) VALUES (2, 'TEJASH1'); 1 row created. SQL> INSERT INTO TEST_SO (COL1,COL2) VALUES (3, 'TEJASH2'); 1 row created. SQL> INSERT INTO TEST_SO (COL1,COL2) VALUES (2, 'TEJASH3'); 1 row created. SQL> INSERT INTO TEST_SO (COL1,COL2) VALUES (2, 'TEJASH'); 1 row created. SQL>
现在,COL2
有 4 个不同的值,COL1
有 3 个不同的值。
使用以下查询获取 COL2
和 4(因为它大于 3(COL1
中的不同值))作为其中的不同值。
您的查询:
SQL> SELECT 2 C.COLUMN_NAME, 3 TO_NUMBER(XMLQUERY('/ROWSET/ROW/C/text()' 4 PASSING XMLTYPE(DBMS_XMLGEN.GETXML( 5 'select count(distinct "' 6 || C.COLUMN_NAME 7 || '") as c ' 8 || 'from "' 9 || C.TABLE_NAME 10 || '"')) RETURNING CONTENT)) AS DISTINCT_VALS 11 FROM USER_TAB_COLUMNS C 12 WHERE C.TABLE_NAME = 'TEST_SO' 13 ORDER BY DISTINCT_VALS DESC NULLS LAST 14 FETCH FIRST ROW WITH TIES; COLUMN_NAME DISTINCT_VALS --------------- ------------- COL2 4 SQL>
干杯!!
自
- 您已准备好使用来自 all_% 视图的 num_rows 和
- 如果您收集了统计数据并且
- 一些可能的差异是acceptable,您可能会使用从all_tab_col_statistics收集的统计数据数据库。
像这样。
select num_distinct, column_name
from all_tab_col_statistics
where table_name = 'TABLE_NAME_UPPERCASE'
order by num_distinct desc
fetch first row with ties;
再次强调,当接受一些公差时请使用这个table。 尽管通常会定期收集 table 统计数据(取决于 DBA),但收集的值与实际值之间可能存在差距。
对于单个 table 你也可以这样的过程:
DECLARE
CURSOR Cols IS
SELECT COLUMN_NAME
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME = 'MY_TABLE_NAME'
ORDER BY COLUMN_ID;
cur INTEGER := DBMS_SQL.OPEN_CURSOR;
columnCount INTEGER := 0;
describeColumns DBMS_SQL.DESC_TAB2;
res INTEGER;
distinctValues NUMBER;
m NUMBER := -1;
c INTEGER := 0;
sqlstr VARCHAR2(30000);
BEGIN
FOR aCol IN Cols LOOP
sqlstr := sqlstr || ',COUNT(DISTINCT '||aCol.COLUMN_NAME||') AS '||aCol.COLUMN_NAME;
END LOOP;
sqlstr := REGEXP_REPLACE(sqlstr, '^,', 'SELECT ')||' FROM MY_TABLE_NAME';
DBMS_SQL.PARSE(cur, sqlStr, DBMS_SQL.NATIVE);
DBMS_SQL.DESCRIBE_COLUMNS2(cur, columnCount, describeColumns);
FOR i IN 1..columnCount LOOP
DBMS_SQL.DEFINE_COLUMN(cur, i, distinctValues);
END LOOP;
res := DBMS_SQL.EXECUTE(cur);
res := DBMS_SQL.FETCH_ROWS(cur); -- no loop required as you get always exactly one row
FOR i IN 1..columnCount LOOP
DBMS_SQL.COLUMN_VALUE(cur, i, distinctValues);
IF distinctValues > m THEN
m := distinctValues;
c := i;
END IF;
DBMS_OUTPUT.PUT_LINE ( describeColumns(i).col_name ||': '|| distinctValues );
END LOOP;
DBMS_OUTPUT.PUT_LINE ( 'Max distinct values at '||describeColumns(c).col_name ||': '|| m );
END;