Oracle - SQL с рекурсивным предложением WHERE - PullRequest
0 голосов
/ 20 октября 2011

У меня есть таблица, в которой хранится иерархия рабочих групп в нашей организации. Это выглядит примерно так:

CREATE TABLE WORKGROUPS  ( 
    WORKGROUPID         NUMBER NULL,
    NAME                VARCHAR2(100) NOT NULL,
    PARENTWORKGROUPID   NUMBER NOT NULL,
    WORKGROUPLEVEL      CHAR(1) DEFAULT 1 NOT NULL,
    CONSTRAINT WORKGROUPS_PK PRIMARY KEY(WORKGROUPID)
)

Например, может быть три уровня рабочих групп:

ID 1 - Sales (PARENTWORKGROUPID = 0)
ID 2 - Business Sales (PARENTWORKGROUPID = 1)
ID 3 - West Coast B2B (PARENTWORKGROUPID = 2)

Итак, родитель 3 - это 2, родитель 2 - 1, а 1 - рабочая группа верхнего уровня без родителей, поэтому мы используем 0.

Теперь у нас есть стол ЗАДАЧ. Каждая строка TASKS имеет столбец WORKGROUPID, который указывает на WORKGROUPID в таблице WORKGROUPS.

Мне нужно написать запрос, который возвращает все ЗАДАЧИ, которые находятся в данной рабочей группе верхнего уровня, например все, что в разделе «Продажи» (которое в приведенном выше примере может быть WORKGROUPIDs 1, 2 или 3. По сути, это рекурсивно запрос.

Я могу придумать несколько способов сделать это, используя LEFT JOIN для проверки каждого уровня, но я бы предпочел держаться подальше от решений, которые жестко кодируют количество уровней, поскольку база данных предназначена для разрешения любого количества ярусы. Любое другое решение, которое я могу придумать, включает изменение схемы таблицы, чего я не могу сделать в данный момент. Есть идеи? Спасибо!

Ответы [ 3 ]

2 голосов
/ 20 октября 2011

Начиная с Oracle 11gR2 , поддерживается рекурсивный синтаксис ANSI WITH, который является альтернативой START WITH / CONNECT BY:

WITH wgs ( workgroupid, name ) AS
(
    SELECT workgroupid, name FROM workgroups WHERE workgroupid = :top-lev-dept
     UNION ALL
    SELECT w.workgroupid, w.name FROM workgroups w, wgs WHERE parentworkgroupid = wgs.workgroupid
)
SELECT ...

Ключ здесь:

WITH view (column_definition) AS
(
    SELECT root rows
     UNION ALL
    SELECT sub rows FROM table JOIN view ON recursion condition
)
1 голос
/ 20 октября 2011

Вы захотите изучить синтаксис START WITH/CONNECT BY.

Что-то вроде:

select * from workgroups
start with parentworkgroupid = 0
connect by prior workgroupid = parentworkgroupid;

Полностью не проверено, но я думаю, что это поможет вам начать.

Надеюсь, это поможет.

1 голос
/ 20 октября 2011

Oracle, кажется, имеет свою собственную версию рекурсии (я использую SQL Server и DB2, которые используют Common Table Expressions для обеспечения рекурсии), но я думаю, что это, возможно, должно получить то, что вы хотите:

WITH WGS (
    WORKGROUPID,
    NAME
) AS (
    SELECT WORKGROUPID,
        NAME
    FROM WORKGROUPS
    START WITH WORKGROUPID = :top-lev-dept
    CONNECT BY WORKGROUPID = PRIOR PARENTWORKGROUPID
)

SELECT DISTINCT T.*
FROM TASKS
INNER JOIN WGS W
    ON (T.WORKGROUPID = W.WORKGROUPID)

Вы, очевидно, изменили бы :top-lev-dept на тот отдел, который искали.

Если это не так, вы можете проверить справочную страницу Oracle по Иерархическим запросам . Это может привести вас в правильном направлении ...

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