2009-06-06 13 views
39

Desidero ottenere la funzionalità di CONNECT BY PRIOR di ORACLE in SQL SERVER 2000/2005/2008?Simulazione di CONNECT BY PRIOR di ORACLE in SQL SERVER

Please help me

+0

Dal momento che sembra voler maggiori dettagli, si dovrà dirci alcuni dati struttura delle tabelle e quello che si sta cercando di fare. Se si dispone di una query di Oracle esistente, che sarebbe un buon inizio .... –

+2

@ John, vedere l'URL che ho postato nella mia risposta, http://www.ibm.com/developerworks/db2/library/techarticle/ dm-0510rielau/- mostra come CONNECT da opere precedenti (una sintassi bello, ma Oracle-proprietaria per ottenere strutture ad albero) e come ottenere lo stesso effetto con (ricorsive) espressioni di tabella comuni, vale a dire, la parola chiave WITH (che è uno standard SQL e implementato in IBM DB2, Microsoft SQL Server e il motore PostgreSQL open-source nella versione 8.4). –

+0

@Alex: grazie, ho visto il tuo post e ho letto l'articolo. Articolo abbastanza carino, e posso capire perché agli utenti Oracle potrebbe piacere la sintassi Oracle. Preferisco la sintassi standard, in quanto è più generale. –

risposta

59

Il metodo standard SQL per implementare query ricorsive, come attuata per esempio da IBM DB2 e SQL Server, è la clausola WITH. Vedere this article per un esempio di traduzione di CONNECT BY in WITH (tecnicamenteCTE ricorsiva) - l'esempio è per DB2 ma credo che funzionerà anche su SQL Server.

Modifica: apparentemente il querant originale richiede un esempio specifico, eccone uno dal sito IBM di cui ho già fornito l'URL. Data una tabella:

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

dove mgrid riferimenti di empid manager di un dipendente, il compito è, ottenere i nomi di tutti coloro che riporta direttamente o indirettamente a Joan. In Oracle, che è un semplice CONNECT:

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

In SQL Server, IBM DB2, o PostgreSQL 8.4 (così come nello standard SQL, per quello che vale la pena ;-), la soluzione perfettamente equivalenti è invece un ricorsiva interrogazione (sintassi più complessa, ma, in realtà, ancora più potenza e flessibilità):

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 

START WITH clausola Oracle diventa il primo nidificata SELECT, il caso base della ricorsione, sia UNION cata con la parte ricorsiva che è solo un altro SELECT.

L'aroma specifico di SQL Server di WITH è naturalmente documentato su MSDN, che fornisce anche linee guida e limitazioni per l'utilizzo di questa parola chiave, nonché diversi esempi.

+1

Spiegare con un esempio. E.g. Prendere alcuni paesi e Stati Come India --State1 - Stato2 l'Australia --AusState1 --AusStae2 Sto cercando la query esatta –

+2

L'esempio indicai, all'URL http://www.ibm.com/developerworks/db2/library/techarticle/dm-0510rielau/, dà la query esatta - copiandolo qui sembra inutile quando si può semplicemente cliccare sul link -!) –

+0

** F ** sezione alla [questo url] (https://docs.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql) era quello che stavo cercando. –

1

Non ho usato connettersi prima, ma una ricerca rapida mostra che è utilizzato per strutture ad albero. In SQL Server, si utilizzano espressioni di tabella comuni per ottenere funzionalità simili.

+2

Si prega di spiegare con un esempio. E.g. Prendete alcuni paesi e Stati Come India --State1 - Stato2 l'Australia --AusState1 --AusStae2 –

10

@Alex Martelli La risposta è fantastica! Ma funziona solo per un elemento alla volta (WHERE name = 'Joan') Se si prende la clausola WHERE, la query restituirà tutte le righe radice insieme ...

ho cambiato un po 'per la mia situazione, così da poter mostra l'intero albero per un tavolo.

definizione di tabella:

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 è letteralmente il livello di una categoria 0: root, 1: primo livello dopo principale, ...)

e la query:

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 

(Non c'è bisogno di concatenare il campo level, ho fatto solo per rendere più leggibile)

la risposta per questa domanda dovrebbe essere qualcosa di simile:

sql return

spero che aiuta qualcuno!

ora, mi sto chiedendo come fare questo su MySQL ... ^^

+0

Ho avuto un problema strano adattare il codice, con una non-gli stessi tipi di dati sul delimitatore e sulla colonna ricorsiva .... ma ha risolto, solo con la definizione della prima lunghezza esplicitamente .... grazie per l'aiuto! –

+0

È possibile evitare la creazione di percorsi da string ('concatenador') per ottenere una struttura ad albero (in modo che i valori di ogni sotto-foglia siano raggruppati insieme senza buchi da un altro elemento)? Oracle 'connect by' costruisce in questo modo gratuitamente. – gavenkoa

Problemi correlati