我正在尝试整理Oracle 11g应用程序的查询,但我遇到了问题。
我将简化真实场景,以便更容易理解(以及保护客户端的数据):
我想要做的是获取我传入的标识符,B和C中唯一值的计数,以及来自连接的XML部分的唯一(和非空)值的计数
我目前的查询是:
SELECT
a.ID
, COUNT(DISTINCT b.VAL) AS B_VAL
, COUNT(DISTINCT c.VAL) AS C_VAL
, COUNT(DISTINCT xml.VAL) AS XML_VAL
FROM a, b, c,
XMLTABLE('/field1/collection/value' passing my_xml_type
COLUMNS VAL VARCHAR2(50) PATH '.') xml
WHERE
a.ID = b.SOME_ID
AND b.OTHER_ID = c.OTHER_ID
AND c.VAL = xml.VAL (+)
现在,如果您忘记计数并返回行,示例结果集可能如下所示:
ID B_VAL C_VAL XML_VAL
---------------------------------------
X abc 123 123
X abc 456 null
X abc 789 789
X abc 789 789
渴望:现在,当我想要执行不同的计数时,我希望它能够返回:
ID B_VAL C_VAL XML_VAL
---------------------------------------
X 1 3 2
实际然而,当我将它们全部作为COUNT(DISTINCT ......)时,这就是我所得到的:
ID B_VAL C_VAL XML_VAL
---------------------------------------
X 1 1 1
ALTERNATIVE: ...如果我从计数中取出DISTINCT,那么我得到:
ID B_VAL C_VAL XML_VAL
---------------------------------------
X 1 4 3
为什么DISTINCT似乎只在特定的B_VAL中运行,但是将其取出导致它在所有行中运行但不考虑唯一性?
是否有另一种方法可以不必将所有连接复制为子查询?我完全错过了这一点吗?
(请注意,我根本不是数据库开发人员,我刚刚被提供帮助,对不起,如果这是一个简单的问题...我已经搜索了谷歌并浏览了这个网站以获得答案但是张贴!)
感谢。
我发现,如果我将XML表连接出来,那么整个B_VAL和C_VAL上的count distinct工作正常......那么,对于Oracle如何处理XML表连接,这可能是奇怪的?
答案 0 :(得分:4)
我无法使用Oracle 10.2.0.3重现您的发现。
这是我的设置:
SQL> CREATE TABLE a AS SELECT 'X' ID FROM dual;
Table created
SQL> CREATE TABLE b AS SELECT 'abc' val, 'X' some_id, 1 other_id FROM dual;
Table created
SQL> CREATE TABLE c AS
2 SELECT 1 other_id, '123' val,
3 XMLTYPE('<field1>
4 <collection><value>123</value></collection>
5 </field1>') my_xml_type
6 FROM dual UNION ALL
7 SELECT 1 other_id, '456' val, NULL FROM dual UNION ALL
8 SELECT 1 other_id, '789' val,
9 XMLTYPE('<field1>
10 <collection><value>789</value></collection>
11 <collection><value>789</value></collection>
12 </field1>') my_xml_type
13 FROM dual;
Table created
查询返回正确的结果:
SQL> SELECT
2 a.ID
3 , COUNT(DISTINCT b.VAL) AS B_VAL
4 , COUNT(DISTINCT c.VAL) AS C_VAL
5 , COUNT(DISTINCT xml.VAL) AS XML_VAL
6 FROM a, b, c
7 , XMLTABLE('/field1/collection/value' passing my_xml_type
8 COLUMNS VAL VARCHAR2(50) PATH '.') xml
9 WHERE a.ID = b.SOME_ID
10 AND b.OTHER_ID = c.OTHER_ID
11 AND c.VAL = xml.VAL (+)
12 GROUP BY a.id;
ID B_VAL C_VAL XML_VAL
-- ---------- ---------- ----------
X 1 3 2
你可以运行这个测试用例吗?
答案 1 :(得分:4)
由于Vincent的测试用例适用于10.2.0.3和11.2.0.2,如果您使用的是11g的早期版本,则可能是错误8816675:XMLexists查询使用选择的DISTINCT返回错误的结果。错误中的示例是指count(distinct)
的问题。您没有明确使用XMLexists,但该错误可能会比标题所暗示的更广泛,或者它可能会在幕后使用。
如果这是问题所在,并且你无法修补,你可以通过包装非计数版本来解决它,这仍然不是很好:
SELECT
A_ID
, COUNT(DISTINCT B_VAL) AS B_VAL
, COUNT(DISTINCT C_VAL) AS C_VAL
, COUNT(DISTINCT XML_VAL) AS XML_VAL
FROM (
SELECT a.ID as A_ID, b.VAL as B_VAL, c.VAL as C_VAL, xml.VAL as XML_VAL
FROM a, b, c
, XMLTABLE('/field1/collection/value' passing my_xml_type
COLUMNS VAL VARCHAR2(50) PATH '.') xml
WHERE a.ID = b.SOME_ID
AND b.OTHER_ID = c.OTHER_ID
AND c.VAL = xml.VAL (+)
)
GROUP BY A_ID;