Как я помню, какой путь PRIOR должен идти в запросах CONNECT BY - PullRequest
6 голосов
/ 06 ноября 2008

У меня ужасная память. Всякий раз, когда я делаю запрос CONNECT BY в Oracle - а я имею в виду каждый раз - мне приходится задумываться, и обычно путем проб и ошибок выясняют, какой аргумент должен указывать ПРИОР.

Я не знаю, почему я не помню - но я не помню.

У кого-нибудь есть удобная мнемоника памяти, так что я всегда помню?

Например:

Чтобы пройти вниз дерево из узла - очевидно, мне пришлось искать это :) - вы делаете что-то вроде:

select
    *
from
    node
connect by
    prior node_id = parent_node_id
start with
    node_id = 1

Итак, я начинаю с node_id из 1 (верхняя часть ветви), и запрос ищет все узлы, где parent_node_id = 1, а затем выполняет итерацию вниз до нижней части дерева.

Чтобы пройти вверх дерево, предшествующее идет на родителя:

select
    *
from
    node
connect by
    node_id = prior parent_node_id
start with
    node_id = 10

Таким образом, начиная где-то вниз по ветви (в данном случае node_id = 10), Oracle сначала получает все узлы, где parent_node_id совпадает с тем, для которого node_id равно 10.

РЕДАКТИРОВАТЬ : я все еще ошибаюсь, поэтому я решил добавить уточняющее изменение, чтобы расширить принятый ответ - вот как я его запомнил сейчас:

select
    *
from
    node
connect by
    prior node_id = parent_node_id
start with
    node_id = 1

Английская версия этого SQL, которую я сейчас читаю как ...

В NODE, начиная со строки в который node_id = 1, следующий ряд выбранный имеет parent_node_id равен node_id от предыдущего (предыдущий) ряд.

РЕДАКТИРОВАТЬ : Quassnoi имеет большое значение - порядок написания SQL делает вещи намного проще.

select
    *
from
    node
start with
    node_id = 1
connect by
    parent_node_id = prior node_id

Мне кажется, это намного понятнее - "начало с" дает первую выбранную строку, а "соединение с" дает следующую строку (и) - в этом случае дочерние элементы node_id = 1.

Ответы [ 3 ]

5 голосов
/ 16 апреля 2009

Я всегда стараюсь поместить выражения в JOIN в следующем порядке:

joined.column = leading.column

Этот запрос:

SELECT  t.value, d.name
FROM    transactions t
JOIN
        dimensions d
ON      d.id = t.dimension

может рассматриваться как «для каждой транзакции, найти соответствующее имя измерения», или «для каждого измерения, найти все соответствующие значения транзакции».

Итак, если я ищу данную транзакцию, я помещаю выражения в следующем порядке:

SELECT  t.value, d.name
FROM    transactions t
JOIN
        dimensions d
ON      d.id = t.dimension
WHERE   t.id = :myid

, и если я ищу измерение, то:

SELECT  t.value, d.name
FROM    dimensions d
JOIN
        transactions t
ON      t.dimension = d.id
WHERE   d.id = :otherid

Первый запрос, скорее всего, будет использовать сканирование индекса сначала на (t.id), затем на (d.id), тогда как последний будет использовать сканирование индекса сначала на (d.id), затем на (t.dimension), и вы можете легко увидеть это в самом запросе: искомые поля находятся слева.

Управляющие и ведомые таблицы могут быть не столь очевидны в JOIN, но это так же ясно, как колокольчик для запроса CONNECT BY: строка PRIOR движется, а не PRIOR движется.

Вот почему этот запрос:

SELECT  *
FROM    hierarchy
START WITH
        id = :root
CONNECT BY
        parent = PRIOR id

означает «найти все строки, для которых parent является заданным id». Этот запрос строит иерархию.

Это можно трактовать так:

connect_by(row) {
  add_to_rowset(row);

  /* parent = PRIOR id */
  /* PRIOR id is an rvalue */
  index_on_parent.searchKey = row->id;

  foreach child_row in index_on_parent.search {
    connect_by(child_row);
  }
}

И этот запрос:

SELECT  *
FROM    hierarchy
START WITH
        id = :leaf
CONNECT BY
        id = PRIOR parent

означает «найти строки, для которых id является заданным parent». Этот запрос создает цепочку предков.

Всегда ставьте PRIOR в правой части выражения.

Думайте о PRIOR column как о константе, в которой будут выполняться поиск во всех ваших строках.

1 голос
/ 06 ноября 2008

Подумайте о порядке выбора записей: столбец обратной ссылки в каждой записи должен соответствовать столбцу обратной ссылки в выбранной записи ПРИОР.

0 голосов
/ 06 ноября 2018

Одной из причин того, что это трудно визуализировать каждый раз, является то, что иногда данные моделируются как id + child_id, а иногда - id + parent_id. В зависимости от того, каким образом моделируются ваши данные, вы должны поместить ключевое слово PRIOR на противоположной стороне.

Уловка, которую я нахожу, заключается в том, чтобы всегда смотреть на мир глазами листового узла дерева, которое вы пытаетесь построить.

Итак (говоря как листовой узел), когда я смотрю вверх, я вижу свой родительский узел, который я также могу называть узлом PRIOR. Ergo, мой ID такой же, как его CHILD_ID. Так что в этом случае PRIOR child_id = id.

Когда данные моделируются наоборот (то есть когда я держу идентификатор моего родителя, а не тот, который держит мой), мой parent_id совпадает с его значением id. Ergo в этом сценарии PRIOR id = parent_id.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...