2010-04-15 12 views
33

È possibile fare riferimento a una query esterna in una sottoquery con MySQL? So che ci sono alcuni casi in cui ciò sia possibile:Riferimento alle tabelle della query esterna in una sottoquery

SELECT * 
FROM table t1 
WHERE t1.date = (
    SELECT MAX(date) 
    FROM table t2 
    WHERE t2.id = t1.id 
); 

ma mi chiedo se una cosa del genere potrebbe funzionare:

SELECT u.username, c._postCount 
FROM User u 
INNER JOIN (
    SELECT p.user, COUNT(*) AS _postCount 
    FROM Posting p 
    --# This is the reference I would need: 
    WHERE p.user = u.id 
    GROUP BY p.user 
) c ON c.user = u.id 
WHERE u.joinDate < '2009-10-10'; 

So che avrei potuto ottenere lo stesso utilizzando un GROUP BY o estraendo la clausola esterna WHERE nella subquery, ma ho bisogno di questo per la generazione automatica di SQL e non posso usare l'alternativa per vari altri motivi.

UPDATE: Siamo spiacenti, la questione ha portato a una certa confusione: La prima query è solo un esempio di lavoro, per dimostrare quello che Non bisogno.

UPDATE 2: Ho bisogno entrambi i confronti u.id = p.user: I primi utenti che hanno aderito conta prima di '2009-10-10', mentre l'altro è una condizione di join che associa correttamente righe della tabella.

+1

perché l'aggiornamento 2? sql analizzerà la tabella derivata "c" e otterrà un elenco completo di tutti gli ID utente e dei loro conteggi dei post. il join 'ON c.user = u.id' restituirà quindi solo gli utenti che soddisfano il vincolo joinDate su' u'. – oedo

+0

Oh, hai assolutamente ragione, sembra che sia un mio errore. Contrassegnerò il tuo commesso come risposta accettata :) – soulmerge

+0

grazie, felice di poter aiutare :) – oedo

risposta

14

Penso che non funzionerà, perché stai facendo riferimento alla tabella derivata "c" come parte di un join.

tuttavia, è possibile estrarre lo WHERE p.user = u.id e sostituirlo con un GROUP BY p.user nella tabella derivata, poiché lo ON c.user = u.id avrà lo stesso effetto.

+0

Thx per la risposta.Ma la tua query farebbe qualcos'altro: conterebbe tutti gli utenti indipendentemente dalla data di iscrizione. * modifica *: mi dispiace, sembra che abbia dimenticato il gruppo interno di – soulmerge

0

molto vicino ...

WHERE t1.date = ( 
    SELECT MAX(date) 

modifica

WHERE t1.date IN ( 
    SELECT MAX(date) 

Dal momento che la query fa un MAX(), sarà sempre tornare solo una data ... dal tuo sub-select ha il filtro sull'ID univoco, dovrebbe darti quello che vuoi.

+2

che non è il problema che l'OP ha, e anche usando = invece di IN funzionerà bene anche. – oedo

+1

oedo's right - aggiornata la domanda per chiarire – soulmerge

14

Non è questo quello che cerchi?

SELECT u.username, c._postCount 
FROM User u 
INNER JOIN (
    SELECT p.user, COUNT(*) AS _postCount 
    FROM Posting p 
    GROUP BY p.user  
) c ON c.user = u.id 
WHERE u.joinDate < '2009-10-10'; 

Il motivo per cui questo funzionerà è che la natura stessa della join verrà filtrata dall'utente. Non è necessario avere una clausola WHERE che filtri esplicitamente l'utente.

+0

Entrambi i join sono obbligatori e servono a scopi diversi - ha aggiornato la domanda – soulmerge

+0

Suppongo che ancora non capisco. Non hai affatto bisogno della clausola where nel mezzo, perché il join tra c e u esclude tutti gli utenti senza post e correla correttamente con i record basati su userid. Ho aggiornato il post per riflettere ciò che intendo. – Jeremy

+0

+1 Hai ragione, quello era il mio errore (oedo era più veloce, però) – soulmerge

-1

Questa soluzione è per postgresql. È possibile utilizzare LATERAL JOIN che è disponibile in postgresql. Ecco come puoi usarlo nella tua query.

SELECT u.username, c._postCount 
FROM User u 
INNER JOIN LATERAL (
    SELECT p.user, COUNT(*) AS _postCount 
    FROM Posting p 
    WHERE p.user = u.id 
    GROUP BY p.user 
) c ON c.user = u.id 
WHERE u.joinDate < '2009-10-10'; 

Ecco un riferimento che è possibile utilizzare. https://medium.com/kkempin/postgresqls-lateral-join-bfd6bd0199df

Problemi correlati