Почему в моем запросе иерархии отображаются повторяющиеся записи? - PullRequest
0 голосов
/ 23 октября 2018

Мое требование - найти все пропущенные дни в месяце.Ниже приведены мои примеры запросов.

CREATE TABLE custom.date_full (
    sno         NUMBER,
    curr_date   DATE);

INSERT INTO custom.date_full VALUES ( 1,'27-sep-2018' );
INSERT INTO custom.date_full VALUES ( 2,'27-sep-2018' );

--Query:1 - RETURNS 4 RECORDS AS EXPECTED
 SELECT  curr_date, 
        TRUNC (curr_date, 'MM') + LEVEL - 1 AS DAY,
        LEVEL 
   FROM (SELECT * FROM custom.date_full WHERE sno=1)
CONNECT BY level<=4
  ORDER BY DAY;

--Query 2: RETURNS 15 RECORDS WITH DUPLICATES
SELECT  curr_date, 
        TRUNC (curr_date, 'MM') + LEVEL - 1 AS DAY,
        LEVEL 
   FROM custom.date_full 
  WHERE sno=1
CONNECT BY level<=4
  ORDER BY DAY;

Мой Query 1 работает хорошо, но Query 2 показывает повторяющиеся записи.Почему?

Ответы [ 2 ]

0 голосов
/ 23 октября 2018

Вы не понимаете, как работает CONNECT BY.Вот пошаговое руководство о том, как Oracle оценивает ваш второй запрос.

Без предложения START WITH каждая строка в вашей таблице будет использоваться в качестве отправной точки или «корня» в вашей иерархии.

Поскольку у вас нет условий CONNECT BY (например, "columnA = PRIOR columnB"), каждая строка в вашей таблице будет считаться дочерней по отношению к любой другой строке.Это будет происходить вечно, пока ваше LEVEL <=4 состояние не будет достигнуто.

Итак,

LEVEL 1
--------
SNO 1
SNO 2

Объяснение: Каждая строка в вашей таблице является отправной точкой своей собственной иерархии (поскольку у вас нет условий START WITH).

LEVEL 2
--------
SNO 1 -> SNO 1
SNO 1 -> SNO 2 
SNO 2 -> SNO 1
SNO 2 -> SNO 2

Объяснение этих 4 строк - и SNO 1, и SNO 2 являются корнями, а для каждого корня SNO 1 и SNO 2 являются дочерними.Итак, 2x2 строки = 4 строки.

LEVEL 3 
-------
SNO 1 -> SNO 1 -> SNO 1
SNO 1 -> SNO 1 -> SNO 2
SNO 1 -> SNO 2 -> SNO 1 
SNO 1 -> SNO 2 -> SNO 2 
SNO 2 -> SNO 1 -> SNO 1
SNO 2 -> SNO 1 -> SNO 2
SNO 2 -> SNO 2 -> SNO 1
SNO 2 -> SNO 2 -> SNO 2

Объяснение этих 8 строк.Начиная с 4 рядов с уровня 2, оба SNO 1 и SNO 2 являются дочерними для каждого, давая 4x2 = 8 строк на уровне 3.

Уровень 4, который я не буду вытягивать, аналогично даст 8x2= 16 строк.

Таким образом, в общей сложности у вас есть 2 + 4 + 8 + 16 = 30 строк.(Это уровень 1 + уровень 2 + уровень 3 + уровень 4).

Затем, после вашей обработки CONNECT BY (показанной выше), применяется условие WHERE, ограничивающееконечные результаты в строках, где значение (на самом низком уровне иерархии) равно SNO = 1.Это ровно половина из 30 строк или 15 строк, что вы и получаете.

0 голосов
/ 23 октября 2018

Использование CONNECT BY создает иерархический запрос.Как правило, это также включает START WITH, который указывает строки, которые являются родителем / корнем иерархического запроса.Когда нет START WITH, все строки в таблице используются как родительские / корневые строки.

В Query 1 родитель / корень - это таблица с 1 строкой:

FROM (SELECT * FROM custom.date_full WHERE sno=1)

В Query 2 родитель / корень - это таблица с 2 строками:

FROM custom.date_full 

Это соотношение START WITH и CONNECT BY определяет, как строки в иерархии будут связаны в результатах.

В Query нет дубликатов, поскольку имеется только одна родительская строкасо связями с несколькими дочерними строками.

В Query 2 есть повторяющиеся результаты, поскольку существует несколько родительских строк со связями с несколькими дочерними строками.


Более общая информация доступна вследующие ресурсы:

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