我想从column_name
中获得一个table_name
和all_tab_columns
的列表(直到这里都没有问题),并且也想为每个给定的列都转到原始表格/列,然后查看发生率最高的最高值是什么。
在下面的查询中,我获得了1个表中1个列的示例的期望值:
select col1
from (SELECT col1, rank () over (order by count(*) desc) as rnk
from T1
Group by col1
)
where rnk = 1
现在我想要这样的东西:
select table_name,
column_name,
xmlquery('/ROWSET/ROW/C/text()'
passing xmltype(dbms_xmlgen.getxml( 'select ' || column_name || ' from (select ' || column_name ||', rank () over (order by count(*) desc) as rnk from '
|| table_name || ' Group by ' || column_name || ') where rnk = 1;'))
returning content) as C
from all_tab_columns
where owner = 'S1'
and table_name in ('T1', 'T2', 'T3', 'T4')
;
但不起作用。这是我得到的错误:
ORA-19202: Error occurred in XML processing
ORA-00933: SQL command not properly ended
ORA-06512: at "SYS.DBMS_XMLGEN", line 176
ORA-06512: at line 1
19202. 00000 - "Error occurred in XML processing%s"
*Cause: An error occurred when processing the XML function
*Action: Check the given error message and fix the appropriate problem
我举一个例子。例如,这是我的两个表; T1:
col.1 col.2 col.3
----- ---------- -----
y m1
y 22 m2
n 45 m2
y 10 m5
和T2:
col.1 col.2 col.3
----- ------- -----
1 germany xxx
2 england xxx
3 germany uzt
3 germany vvx
8 US XXX
如此
以此类推。
答案 0 :(得分:1)
报告给您的重要错误是这个:
ORA-00933: SQL command not properly ended
从dbms_xmlgen.getxml()
调用中的查询中删除分号:
select table_name,
column_name,
xmlquery('/ROWSET/ROW/C/text()'
passing xmltype(dbms_xmlgen.getxml( 'select ' || column_name || ' from (select ' || column_name ||', rank () over (order by count(*) desc) as rnk from '
|| table_name || ' Group by ' || column_name || ') where rnk = 1'))
-------^ no semicolon here
returning content) as C
from all_tab_columns
...
尽管如此,您的XPath也似乎是错误的。您在寻找/ROWSET/ROW/C
,但是C
是整个表达式的列别名,而不是要计算的列。您需要为查询中的列名 加上别名,并在XPath中使用它:
select table_name,
column_name,
xmlquery('/ROWSET/ROW/COL/text()'
-- ^^^
passing xmltype(dbms_xmlgen.getxml( 'select ' || column_name || ' as col from (select ' || column_name ||', rank () over (order by count(*) desc) as rnk from '
-- ^^^^^^
|| table_name || ' Group by ' || column_name || ') where rnk = 1'))
returning content) as C
from all_tab_columns
...
您的样本数据将得到:
TABLE_NAME COLUMN_NAME C
------------------------------ ------------------------------ ----------
T1 col.1 y
T1 col.2 224510
T1 col.3 m2
T2 col.1 3
T2 col.2 germany
T2 col.3 xxx
XMLQuery返回XMLtype结果,您的客户端显然将其显示为(XMLTYPE)
。您可能可以更改该行为-例如在Sql Developer中从工具->首选项->数据库->高级-> DIsplay XMl值在网格中。但是,您也可以将结果转换为字符串,使用getStringVal()
返回varchar2
(如果具有CLOB值,则返回getClobVal()
,这可能会导致其他问题):
select table_name,
column_name,
xmlquery('/ROWSET/ROW/COL/text()'
passing xmltype(dbms_xmlgen.getxml( 'select ' || column_name || ' as col from (select ' || column_name ||', rank () over (order by count(*) desc) as rnk from '
|| table_name || ' Group by ' || column_name || ') where rnk = 1'))
returning content).getStringVal() as C
-- ^^^^^^^^^^^^^^^
from all_tab_columns
...
如您所见,由于数目相等,这在平局中并没有达到您的预期-在您的示例中,发现T1."col.2"
的值不同(null,10、22、45 )每个出现一次; XMLQuery将它们全部组合在一起,形成一个结果。在这种情况下,您需要决定要发生什么。如果只想看一个,则需要在解析的order by
子句中指定如何决定打破平局。
我实际上想查看所有结果,但是我希望能在不同的行中看到它们
允许使用XMLTable代替XMLQuery的另一种方法:
select table_name, column_name, value
from (
select atc.table_name, atc.column_name, x.value, x.value_count,
rank() over (partition by atc.table_name, atc.column_name
order by x.value_count desc) as rnk
from all_tab_columns atc
cross join xmltable(
'/ROWSET/ROW'
passing xmltype(dbms_xmlgen.getxml(
'select "' || column_name || '" as value, count(*) as value_count '
|| 'from ' || table_name || ' '
|| 'group by "' || column_name || '"'))
columns value varchar2(4000) path 'VALUE',
value_count number path 'VALUE_COUNT'
) x
where atc.owner = user
and atc.table_name in ('T1', 'T2', 'T3', 'T4')
)
where rnk = 1;
内部查询将all_tab_columns
交叉连接到XMLTable,该表执行更简单的dbms_xmlgen.get_xml()
调用以仅获取每个值及其计数,从生成的XML中提取值和计数作为关系数据,并且包括排名功能作为该子查询的一部分,而不是XML生成之内。如果您单独运行子查询,则会看到所有possibel值及其计数以及每个值的排名。
外部查询仅对排名进行过滤,并向您显示子查询中排名第一的相关列。