Почему изменение порядка таблиц в предложении FROM в Oracle приводит к ошибкам при попытке выполнить JOIN - PullRequest
0 голосов
/ 11 февраля 2019

Если эти операторы могут быть представлены SELECT a FROM x,y JOIN z ON y.id = z.id WHERE ... Изменение порядка x и y либо сработает, либо вызовет ошибку.Ниже приведены два полных запроса и точная ошибка, возникающая в SQL Developer


Пример 1:

(фрагмент) FROM (SELECT ...), persons prsn LEFT OUTER JOIN point_summaries psum ON psum.prsn_id prsn.prsn_id

SELECT prsn.prsn_id, person_points.points, psum.psum_points_available
  FROM (SELECT prsn_id prsn_id, sum(points) points
          FROM (SELECT prsn.prsn_id, SUM(pnts.pnts_points) points
                  FROM points pnts,
                       invoices inv,
                       transaction_details tdet,
                       orders ord,
                       persons prsn
                 WHERE pnts.pnts_status = 'R'
                   AND tdet.tdet_id     = pnts.tdet_id
                   AND tdet.inv_id      = inv.inv_id
                   AND inv.ord_id       = ord.ord_id
                   AND ord.prsn_id_byr  = prsn.prsn_id
              GROUP BY prsn.prsn_id
                       UNION ALL
                SELECT prsn.prsn_id, SUM(pnts.pnts_points) points
                  FROM points pnts,
                       reward_order_details rdet,
                       reward_orders rord,
                       persons prsn
                 WHERE pnts.pnts_status = 'R'
                   AND rdet.rdet_id     = pnts.rdet_id
                   AND rord.rord_id     = rdet.rord_id
                   AND rord.prsn_id     = prsn.prsn_id
              GROUP BY prsn.prsn_id
                       UNION ALL
                SELECT prsn.prsn_id, SUM(pnts.pnts_points) points
                  FROM points pnts,
                       miscellaneous_points misp,
                       persons prsn
                 WHERE pnts.pnts_status = 'R'
                   AND pnts.mpts_id     = misp.mpts_id
                   AND misp.prsn_id     = prsn.prsn_id
              GROUP BY prsn.prsn_id
                   UNION ALL
                SELECT prsn.prsn_id, SUM(pnts.pnts_points) points
                  FROM points pnts,
                       transaction_details tdet,
                       returns rtn,
                       persons prsn
                 WHERE pnts.pnts_status = 'R'
                   AND tdet.tdet_id    = pnts.tdet_id
                   AND tdet.rtn_id     = rtn.rtn_id
                   AND rtn.prsn_id_byr = prsn.prsn_id
              GROUP BY prsn.prsn_id)
        GROUP BY prsn_id) person_points,
        persons prsn
LEFT OUTER JOIN point_summaries psum on psum.prsn_id = prsn.prsn_id
  WHERE person_points.points > 0
    AND person_points.prsn_id = prsn.prsn_id
    AND ((NOT psum.psum_points_available = person_points.points)
        OR NOT EXISTS (SELECT 1
                         FROM point_summaries x
                        WHERE x.prsn_id = prsn.prsn_id))

Возвращает aуспешная таблица:

| prsn_id | points | psum_points_available |
|------------------------------------------|
| 111111  | 676    | 287                   |
| 111112  | 11672  | 1971                  |
| 111113  | 137    | 89                    |
| 111114  | 156    | (null)                |
| 111115  | 5111   | 570                   |
| 111116  | 280    | (null)                |

Пример 2:

(фрагмент) FROM persons prsn, (SELECT ...) LEFT OUTER JOIN point_summaries psum ON psum.prsn_id prsn.prsn_id

SELECT prsn.prsn_id, person_points.points, psum.psum_points_available
  FROM (SELECT prsn_id prsn_id, sum(points) points
          FROM persons prsn,
               (SELECT prsn.prsn_id, SUM(pnts.pnts_points) points
                  FROM points pnts,
                       invoices inv,
                       transaction_details tdet,
                       orders ord,
                       persons prsn
                 WHERE pnts.pnts_status = 'R'
                   AND tdet.tdet_id     = pnts.tdet_id
                   AND tdet.inv_id      = inv.inv_id
                   AND inv.ord_id       = ord.ord_id
                   AND ord.prsn_id_byr  = prsn.prsn_id
              GROUP BY prsn.prsn_id
                       UNION ALL
                SELECT prsn.prsn_id, SUM(pnts.pnts_points) points
                  FROM points pnts,
                       reward_order_details rdet,
                       reward_orders rord,
                       persons prsn
                 WHERE pnts.pnts_status = 'R'
                   AND rdet.rdet_id     = pnts.rdet_id
                   AND rord.rord_id     = rdet.rord_id
                   AND rord.prsn_id     = prsn.prsn_id
              GROUP BY prsn.prsn_id
                       UNION ALL
                SELECT prsn.prsn_id, SUM(pnts.pnts_points) points
                  FROM points pnts,
                       miscellaneous_points misp,
                       persons prsn
                 WHERE pnts.pnts_status = 'R'
                   AND pnts.mpts_id     = misp.mpts_id
                   AND misp.prsn_id     = prsn.prsn_id
              GROUP BY prsn.prsn_id
                   UNION ALL
                SELECT prsn.prsn_id, SUM(pnts.pnts_points) points
                  FROM points pnts,
                       transaction_details tdet,
                       returns rtn,
                       persons prsn
                 WHERE pnts.pnts_status = 'R'
                   AND tdet.tdet_id    = pnts.tdet_id
                   AND tdet.rtn_id     = rtn.rtn_id
                   AND rtn.prsn_id_byr = prsn.prsn_id
              GROUP BY prsn.prsn_id)
        GROUP BY prsn_id) person_points
LEFT OUTER JOIN point_summaries psum on psum.prsn_id = prsn.prsn_id
  WHERE person_points.points > 0
    AND person_points.prsn_id = prsn.prsn_id
    AND ((NOT psum.psum_points_available = person_points.points)
        OR NOT EXISTS (SELECT 1
                         FROM point_summaries x
                        WHERE x.prsn_id = prsn.prsn_id))

Возвращает ошибку:

ORA-00904: "PRSN"."PRSN_ID": invalid identifier
00904. 00000 -  "%s: invalid identifier"
*Cause:    
*Action:
Error at Line: 49 Column: 16

Iискал ответ, но все, что я нашел, похоже, говорит о том, что порядок FROM не должен иметь значения.Это начинает иметь значение, если вы используете подзапрос SELECT для генерации временной таблицы в предложении FROM вашего запроса?Или, может быть, здесь происходит что-то еще, что мне не хватает, чтобы кто-то мог просветить меня.

Заранее спасибо.

1 Ответ

0 голосов
/ 11 февраля 2019

Проблема не в подзапросе или левом соединении.Проблема в том, что вы смешиваете неявный и явный синтаксис объединения.

В качестве упрощенного примера:

select *
from dual a, dual b join dual c on c.dummy = b.dummy
where b.dummy = a.dummy;

D D D
- - -
X X X

select *
from dual b, dual a join dual c on c.dummy = b.dummy
where b.dummy = a.dummy;

ORA-00904: "B"."DUMMY": invalid identifier

Явный синтаксис JOIN имеет приоритет неявного соединения отсписок таблиц через запятую в FROM;таким образом, первый запрос фактически выполняет:

select *
from dual b
join dual c on c.dummy = b.dummy
join dual a on b.dummy = a.dummy;

D D D
- - -
X X X

, в то время как второй эффективно выполняет:

select *
from dual a
join dual c on c.dummy = b.dummy
join dual b on b.dummy = a.dummy;

ORA-00904: "B"."DUMMY": invalid identifier

С этим синтаксисом более очевидно, что в первой точке вы ссылаетесь на b.dummy,псевдоним таблицы b еще не определен, поэтому возникает ошибка.

Не рекомендуется смешивать два стиля соединения.Я бы посоветовал вам стандартизировать «новый» явный синтаксис объединения:

FROM (SELECT ...) person_points
JOIN persons prsn ON prsn.prsn_id = person_points.prsn_id
LEFT OUTER JOIN point_summaries psum ON psum.prsn_id = prsn.prsn_id

или

FROM persons prsn
JOIN (SELECT ...) person_points ON person_points.prsn_id = prsn.prsn_id
LEFT OUTER JOIN point_summaries psum ON psum.prsn_id = prsn.prsn_id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...