19 messaggi dal 19 dicembre 2011
ok facendo le modifiche che mi hai detto il risultato è sempre lo stesso errore:

#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1 internal_post.id_post from Post as internal_post whe' at line 40

internal_post da dove la prende???
non ho una tabella con questo nome
42 messaggi dal 13 settembre 2007
il problema è che MySql non supporta la parola chiave TOP.

Sostituisci
      
select top 1 internal_post.id_post 
from post as internal_post 
where external_post.id_room = internal_post.id_room
order by internal_post.data desc

con
      
select internal_post.id_post 
from post as internal_post 
where external_post.id_room = internal_post.id_room
order by internal_post.data desc LIMIT 0,1

Ossia togli "top 1" e dopo la WHERE metti LIMIT 0,1 .
Lo stesso con l'altra query interna con il "select top 1" quella che si riferisce ad internal_risposta]
Modificato da roland79 il 21 dicembre 2011 14.26 -
19 messaggi dal 19 dicembre 2011
il problema rimane, in quanto non riesce a vedere, internal_post...

cmq togliedo TOP 1 e mettendo LIMIT 0,1 l'errore che mi da è:

#1241 - Operand should contain 1 column(s)

dai che ci siamo quasi....
Modificato da Rare il 22 dicembre 2011 09.29 -
42 messaggi dal 13 settembre 2007
Ciao ora non hai più scusa :). Mi sono installato MySql, ho creato le tabelle e rifatto la SQL. Questo è il risultato e mi funziona:
select  Rooms.id_room
,  Rooms.room
,  Ifnull(NDiscussioni,0) as NDiscussioni
,  Ifnull(NRisposte,0) as NRisposte
,  max_post_data
,  nome_utente_post
,  max_risposta_data 
,  nome_utente_risposta
,  (case when Ifnull(max_risposta_data,'1900-01-01') > Ifnull(max_post_data,'1900-01-01') then 'risposta' else 'post' end) as last_activity_type
,  (case when Ifnull(max_risposta_data,'1900-01-01') > Ifnull(max_post_data,'1900-01-01') then max_risposta_data else max_post_data end) as last_activity_data
,  (case when Ifnull(max_risposta_data,'1900-01-01') > Ifnull(max_post_data,'1900-01-01') then nome_utente_risposta else nome_utente_post end) as last_activity_user
from  Rooms /*parto dalle stanze*/
/*Per ogni stanza (group by id_room), vado a recuperare il numero di discussioni count(id_post)*/
left  join
(  
  select id_room, count(id_post) as NDiscussioni
  from  Post
  group by id_room
 )  as posts
 on  Rooms.id_room = posts.id_room
 /*Per ogni stanza (group by id_room), vado a recuperare il numero di risposte count(id_risposta)*/
 left  join
 (
  select id_room, count(id_risposta ) as NRisposte
  from  Risposte
  group by id_room  
 )  as risposte
 on  Rooms.id_room = risposte.id_room
 /*Prendo tutti i post presenti nel db e per ogni stanza prendo l'ultimo disponibile. Per prendere l'ultimo, faccio una subquery in cui a parità di id_room, prendo il post piu recente.*/
 left  join 
 (
  select  external_post.id_room
  ,external_post.id_post
  ,external_post.data            as max_post_data 
  ,utenti.id_utente            as id_utente_post  
  ,utenti.Nome + ' ' + utenti.Cognome    as nome_utente_post
  from  Post as external_post
  join  Utenti
  on    external_post.id_utente = Utenti.id_utente
  where  id_post = (
            /*per la stanza considerata nella query padre (external_post.id_room = = internal_post.id_room), prendo l'ultimo post disponibile... per fare ciò ordino tutti i record per data descrescente e prendo il primo (LIMIT 0,1)*/
            select internal_post.id_post 
            from Post as internal_post 
            where external_post.id_room = internal_post.id_room
            order by internal_post.data desc LIMIT 0,1
             )
 )  as post_data
  on  Rooms.id_room = post_data.id_room
 /*recupero l'ultima risposta per post. Il ragionamento è analogo a quello fatto in precedenza per l'ultimo post*/
  left  join 
 (
  select  external_risposta.id_post
  ,external_risposta.data          as max_risposta_data 
  ,utenti.id_utente            as id_utente_risposta
  ,utenti.Nome + ' ' + utenti.Cognome    as nome_utente_risposta
  from  Risposte    as external_risposta
  join  Utenti
  on    external_risposta.id_utente = Utenti.id_utente
  where  id_risposta = (/*per ogni post recupero l'ultima risposta*/
            select internal_risposta.id_risposta 
            from Risposte as internal_risposta 
            where external_risposta.id_post = internal_risposta.id_post
            order by internal_risposta.data desc LIMIT 0,1
             )
 )  as risposta_data
  on  post_data.id_post = risposta_data.id_post


Ciao
Modificato da roland79 il 23 dicembre 2011 13.35 -
19 messaggi dal 19 dicembre 2011
fantastico...
sei un grande...

però ti devo chiedere un altro favore...

a me servirebbe anche il nome della room e non solo l'id.

ho provato a mettere rooms.room nelle select interne ma non va...

ultima cortesia mi spieghi, gentilmente, come è struttrata la query...

nel senso che se un giorno mi serve una cosa del genere (così complicata), so fare senza stressarti la vita... ;)
42 messaggi dal 13 settembre 2007
Ciao non devi mettere Rooms.room nelle select interne ma in quella esterna:
select  Rooms.id_room
,  Rooms.room
/*aggiungere qui altri campi separati da ,*/
,  Ifnull(NDiscussioni,0) as NDiscussioni
,  Ifnull(NRisposte,0) as NRisposte
,  max_post_data
,  nome_utente_post
...

Come vedi ho aggiunto Rooms.room come secondo campo ma nella query globale non nelle query interne. Le query interne servono solo per preparare i dati da visualizzare.
Se hai la necessità di esporre altri campi come Rooms.room ad esempio Rooms.room_floor o altro, aggiungile nella query principale dove ti ho inserito il commento.

Per quanto riguarda la spiegazione e l'aggiunta del nuovo campo, ho aggiornato il precedente post per non stare a riscrivere tutta la query visto che è lunghetta.

Il mio suggerimento è quello di fare la query a pezzi... parti dall'argomento principale (le Rooms), per ognuna di quelle estrai i dati che ti servono. Inoltre le varie query all'interno delle LEFT JOIN le puoi tranquillamente lanciare DA SOLE per vedere che dati ti estraggono.

Ricapitolando:
1) parti dalle Rooms (SELECT Rooms.* FROM ROOMS)
2) Calcoli il numero di discussioni e risposte in 2 QUERY SEPARATE:
  
  select id_room, count(id_post) as NDiscussioni
  from  Post
  group by id_room
...
  select id_room, count(id_risposta ) as NRisposte
  from  Risposte
  group by id_room  

3) Calcoli l'ultimo post per ogni id_Room
  select  external_post.id_room
  ,external_post.id_post
  ,external_post.data            as max_post_data 
  ,utenti.id_utente            as id_utente_post  
  ,utenti.Nome + ' ' + utenti.Cognome    as nome_utente_post
  from  Post as external_post
  join  Utenti
  on    external_post.id_utente = Utenti.id_utente
  where  id_post = (/*per ogni stanza recupero l'ultimo post*/
            select internal_post.id_post 
            from Post as internal_post 
            where external_post.id_room = internal_post.id_room
            order by internal_post.data desc LIMIT 0,1
             )

4) fai la stesso cosa per le risposte di ogni post
select  external_risposta.id_post
  ,external_risposta.data          as max_risposta_data 
  ,utenti.id_utente            as id_utente_risposta
  ,utenti.Nome + ' ' + utenti.Cognome    as nome_utente_risposta
  from  Risposte    as external_risposta
  join  Utenti
  on    external_risposta.id_utente = Utenti.id_utente
  where  id_risposta = (/*per ogni post recupero l'ultima risposta*/
            select internal_risposta.id_risposta 
            from Risposte as internal_risposta 
            where external_risposta.id_post = internal_risposta.id_post
            order by internal_risposta.data desc LIMIT 0,1
             )

5) metti assieme le cose con le eventuali LEFT JOIN.

Le query al punto 3) 4) servono solo per i post e per le risposte... non ti servono per avere informazioni sulle stanze, quindi non hanno bisogno di essere legate internamente alla Rooms (non ha senso quindi aggiungere qui il campo Rooms.room)... Il legame avviene per ultimo inserendo le varie LEFT JOIN.

Spero di essere stato chiaro.

Ciao e buone feste :)
PS: un'ultima cosa... prima dicevi che non riuscivi a trovare le tabelle internal_post, external_post ecc... queste non sono tabelle ma "alias" di tabelle... in pratica dei soprannomi che si danno alle tabelle per rendere più chiara la query e per evitare possibili uguaglianze di nomi.
Per esempio:
select pippo.nome, pippo.cognome
from   persona as pippo
where pippo.nome = 'personaggio disney'


In pratica alla tabella "persona" do il nome di "pippo" perchè almeno è più chiaro a chi mi sto riferendo.
Modificato da roland79 il 23 dicembre 2011 13.50 -

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.