Symulacja CONNECT by PRIOR of ORACLE w SQL SERVER
Chciałbym uzyskać funkcjonalność CONNECT by PRIOR of Oracle w SQL SERVER 2000/2005/2008?
Proszę pomóż mi
3 answers
Standardowym sposobem implementacji zapytań rekurencyjnych SQL, zaimplementowanym np. przez IBM DB2 i SQL Server , jest klauzula WITH
. Zobacz ten artykuł dla przykładu tłumaczenia CONNECT BY
na WITH
(technicznie a rekurencyjne CTE) -- przykład dotyczy DB2, ale wierzę, że będzie działał również na SQL Server.
Edit: najwyraźniej oryginalny querant wymaga konkretnego przykładu, oto jeden z witryny IBM, którego adres URL już podałem. Given a tabela:
CREATE TABLE emp(empid INTEGER NOT NULL PRIMARY KEY,
name VARCHAR(10),
salary DECIMAL(9, 2),
mgrid INTEGER);
Gdzie mgrid
odwołuje się do menedżera pracownika empid
, zadaniem jest uzyskanie nazwisk wszystkich, którzy zgłaszają się bezpośrednio lub pośrednio do Joan
. W Oracle jest to proste CONNECT
:
SELECT name
FROM emp
START WITH name = 'Joan'
CONNECT BY PRIOR empid = mgrid
W SQL Server, IBM DB2 lub PostgreSQL 8.4 (jak również w standardzie SQL, jeśli to coś warte;-), idealnym rozwiązaniem jest zamiast tego rekurencyjne zapytanie (bardziej złożona składnia, ale w rzeczywistości jeszcze większa moc i elastyczność): {]}
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
Klauzula Oracle ' s START WITH
staje się pierwszym zagnieżdżonym SELECT
, podstawowym przypadkiem rekurencji, aby być UNION
ed z częścią rekurencyjną, która jest po prostu kolejnym SELECT
.
Specyficzny smak WITH
SQL Server jest oczywiście udokumentowany na MSDN , który również podaje wytyczne i ograniczenia dotyczące używania tego słowa kluczowego, a także kilka przykładów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-06 23:38:23
@Alex Martelli
'Odpowiedź jest świetna!
Ale działa tylko dla jednego elementu w czasie (WHERE name = 'Joan'
)
Jeśli usuniesz klauzulę WHERE
, zapytanie zwróci wszystkie wiersze główne razem...
Zmieniłem trochę dla mojej sytuacji, więc może pokazać całe drzewo za stół.
Definicja Tabeli:
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
jest dosłownie poziomem kategorii 0: root, 1: Pierwszy poziom po root, ...)
I zapytanie:
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
(nie trzeba konkatenować pola level
, zrobiłem tylko aby uczynić bardziej czytelnym)
Odpowiedź na to zapytanie powinna brzmieć mniej więcej tak:
Mam nadzieję, że to komuś pomoże!Teraz zastanawiam się jak to zrobić na MySQL... ^^
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-09 19:12:14
Nie używałem connect by prior, ale szybkie wyszukiwanie pokazuje, że jest używany do struktur drzewiastych. W SQL Server używasz popularnych wyrażeń tabel, aby uzyskać podobną funkcjonalność.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-06 14:39:31