Моделирование CONNECT BY PRIOR ORACLE в SQL SERVER - PullRequest
40 голосов
/ 06 июня 2009

Я хотел бы получить функциональность CONNECT BY PRIOR ORACLE в SQL SERVER 2000/2005/2008?

Пожалуйста, помогите мне

Ответы [ 3 ]

64 голосов
/ 06 июня 2009

Стандартный способ SQL для реализации рекурсивных запросов, например, реализованный. IBM DB2 и SQL Server , это предложение WITH. В этой статье приведен пример перевода CONNECT BY в WITH (технически рекурсивный CTE ) - пример для DB2, но я считаю, что он будет работать на SQL Сервер также.

Редактировать: очевидно, оригинальный оригинал требует конкретного примера, вот один из сайта IBM, URL которого я уже дал. С учетом таблицы:

CREATE TABLE emp(empid  INTEGER NOT NULL PRIMARY KEY,
                 name   VARCHAR(10),
                 salary DECIMAL(9, 2),
                 mgrid  INTEGER);

где mgrid ссылается на empid менеджера сотрудника, задача состоит в том, чтобы получить имена всех, кто прямо или косвенно сообщает Joan. В Oracle это просто CONNECT:

SELECT name 
  FROM emp
  START WITH name = 'Joan'
  CONNECT BY PRIOR empid = mgrid

В SQL Server, IBM DB2 или PostgreSQL 8.4 (а также в стандарте SQL, для чего это стоит ;-), совершенно эквивалентным решением является рекурсивный запрос (более сложный синтаксис, но, на самом деле, даже более мощность и гибкость):

WITH n(empid, name) AS 
   (SELECT empid, name 
    FROM emp
    WHERE name = 'Joan'
        UNION ALL
    SELECT nplus1.empid, nplus1.name 
    FROM emp as nplus1, n
    WHERE n.empid = nplus1.mgrid)
SELECT name FROM n

Предложение Oracle START WITH становится первым вложенным SELECT, базовым случаем рекурсии, для UNION редактирования с рекурсивной частью, которая является просто другой SELECT.

Специфический вариант SQL Server WITH, конечно, задокументирован в MSDN , в котором также приведены рекомендации и ограничения по использованию этого ключевого слова, а также несколько примеров.

10 голосов
/ 09 апреля 2012

@Alex Martelli отличный ответ! Но это работает только для одного элемента за раз (WHERE name = 'Joan') Если вы уберете предложение WHERE, запрос вернет все корневые строки вместе ...

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

определение таблицы:

CREATE TABLE [dbo].[mar_categories] ( 
    [category]  int IDENTITY(1,1) NOT NULL,
    [name]      varchar(50) NOT NULL,
    [level]     int NOT NULL,
    [action]    int NOT NULL,
    [parent]    int NULL,
    CONSTRAINT [XPK_mar_categories] PRIMARY KEY([category])
)

(level буквально является уровнем категории 0: корень, 1: первый уровень после корня, ...)

и запрос:

WITH n(category, name, level, parent, concatenador) AS 
(
    SELECT category, name, level, parent, '('+CONVERT(VARCHAR (MAX), category)+' - '+CONVERT(VARCHAR (MAX), level)+')' as concatenador
    FROM mar_categories
    WHERE parent is null
        UNION ALL
    SELECT m.category, m.name, m.level, m.parent, n.concatenador+' * ('+CONVERT (VARCHAR (MAX), case when ISNULL(m.parent, 0) = 0 then 0 else m.category END)+' - '+CONVERT(VARCHAR (MAX), m.level)+')' as concatenador
    FROM mar_categories as m, n
    WHERE n.category = m.parent
)
SELECT distinct * FROM n ORDER BY concatenador asc

(вам не нужно объединять поле level, я просто сделал его более читабельным)

ответ на этот запрос должен выглядеть примерно так:

sql return

Надеюсь, это кому-нибудь поможет!

Теперь мне интересно, как это сделать на MySQL ... ^^

1 голос
/ 06 июня 2009

Ранее я не использовал connect, но быстрый поиск показывает, что он используется для древовидных структур. В SQL Server вы используете общие табличные выражения для получения аналогичной функциональности.

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