2010-01-12 7 views
25

Mi piacerebbe ottenere in una query un post e il primo commento associato al post. Ecco come lo faccio in PostgreSQL:La sottoquery Oracle non vede la variabile dal livello esterno del blocco 2 su

SELECT p.post_id, 
(select * from 
(select comment_body from comments where post_id = p.post_id 
order by created_date asc) where rownum=1 
) the_first_comment 
FROM posts p 

e funziona perfettamente.

Tuttavia, in Oracle viene visualizzato un errore ORA-00904 p.post_id: identificatore non valido.

Sembra funzionare bene per una sottoselezione, ma non riesco a ottenere il commento con uno solo a causa del fatto che ho bisogno di utilizzare rownum (nessun limite/offset in Oracle).

Cosa sto facendo di sbagliato qui?

+0

Probabilmente, si usa qualcosa 'LIMIT 1' su' PostgreSQL': non supporta 'rownum'. – Quassnoi

+0

sì, ovviamente sul postgres limite utilizzato – user248789

risposta

44

No, Oracle non correlano le sottoquery nidificate a più di un livello (e nemmeno MySQL).

Questo è un problema ben noto.

Utilizzare questa:

SELECT p.post_id, c.* 
FROM posts 
JOIN (
     SELECT c.*, ROW_NUMBER() OVER (PARTITION BY post_id ORDER BY created_date ASC) AS rn 
     FROM comments c 
     ) c 
ON  c.post_id = p.post_id 
     AND rn = 1 
+1

Grazie Quassnoi, questa è ovviamente una buona risposta (anche se stupidamente complessa, ma probabilmente PostgreSQL mi ha rovinato un po '). Ci scusiamo per non aver risposto prima ma il mio datore di lavoro non gradisce che io usi StackOverflow bloccando il sito e utilizzando il proxy posso solo fare domande, non commentare (probabilmente un problema con il codice SO Ajax). – user248789

+2

Se si diventa creativi, è possibile aggirare questo problema spostando la variabile filtrata su un livello nella sottoquery. – chotchki

+1

+1 per indicare il problema di Oracle e mostrare una soluzione alternativa. PS: Mi piace Oracle, ma a volte Postgres è molto più facile da usare. – Christian

3

Se avete bisogno di SQL che è indipendente dalla piattaforma, questo funzionerà:

SELECT p.post_id 
    , c.comment_body 
    FROM posts p 
    , comments c 
WHERE p.post_id = c.post_id 
    AND c.created_date IN 
     (SELECT MIN(c2.created_date) 
      FROM comments c2 
      WHERE c2.post_id = p.post_id 
     ); 

Ma presuppone che (post_id, CREATED_DATE) è la chiave primaria di commenti . In caso contrario, riceverai più di un messaggio di riga con commenti con lo stesso created_date.

Inoltre, è probabile che sia più lento della soluzione che utilizza l'analisi, fornita da Quassnoi.

+0

Sarebbe un po 'pericoloso. La data di creazione non può essere garantita come unica. Ma usare solo MIN (comment_id) dovrebbe andare bene dato che è preso dalla sequenza. Ho usato la soluzione di Quassnoi, però. – user248789