PL / SQL SELECT с несколькими COUNT (DISTINCT xxx) - неожиданные результаты - PullRequest
4 голосов
/ 08 июня 2011

Я пытаюсь собрать запрос для приложения Oracle 11g, и у меня возникла проблема.

Я упросту реальный сценарий, чтобы его было легче понять (а также защитить).данные клиента):

  • Таблица A является базовой таблицей.У него есть известный идентификатор, который я передаю запросу.
  • Для каждой записи в таблице A может быть несколько записей в таблице B. Таблица B содержит интересующее меня значение.
  • Для каждой записи в таблице B также может быть несколько записей в таблице C. Таблица C содержит другое интересующее меня значение.
  • У меня также есть фрагмент XML, содержащий список значений, которые могут илиможет не совпадать со значениями, представляющими интерес в таблице C.
  • Запрос выполняет внешнее соединение с XML, чтобы при наличии совпадающего значения он возвращал значение снова, в противном случае он равен нулю.

То, что я хочу сделать, это вернуть идентификатор, который я передал, количество уникальных значений в 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

DESIRED: Теперь, когда я хочу сделать разные подсчеты, я бы хотел, чтобы он вернулся:

ID     B_VAL     C_VAL     XML_VAL
---------------------------------------
X      1         3         2

ACTUAL: Однако, это то, что я получаю, когдаУ меня все они как 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, но его удаление заставляет его работать во всех строках, но без учета уникальности?

Есть ли другой способделать это, что не требует репликации всех объединений как подзапрос?Я полностью упустил суть?

(Обратите внимание, я вообще не являюсь разработчиком БД, меня только что вытащили, чтобы помочь, извините, если это простая проблема ... ЯХотя, я искал в Google и просматривал этот сайт для ответов перед публикацией!)

Спасибо.


Я обнаружил, что если я возьму XML-таблицу, соединяющуюся, то подсчитаем разные работыХорошо для B_VAL и C_VAL ... Так что, может быть, странно, как Oracle обрабатывает объединения таблиц XML?

Ответы [ 2 ]

4 голосов
/ 08 июня 2011

Поскольку тестовый пример Винсента работает в 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;
4 голосов
/ 08 июня 2011

Я не могу воспроизвести ваши результаты с 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

Можете ли вы запустить этот контрольный пример?

...