19 messaggi dal 19 dicembre 2011
salve a tutti vi chiedo una mano per quanto riguarda una query...
da quello che ho potuto capire mi servono tre join e quindi mi si complica la vita...
vi spiego:

ho 4 tabelle:

POST
- id_utente
- id_post (chiave)
- titolo
- testo
- id_room
- data

RISPOSTE
- id_utente
- id_risposta (chiave)
- id_post
- testo
- id_room
- data

ROOMS
- id_room (chiave)
- room

UTENTI
- id_utente (chiave)
- nome
- cognome
- username
- password

ora avendo queste tre tabelle devo fare una query che mi dia come risultato una cosa del genere:

room - NDiscussioni - NRisposte - Data&Userneme (dell'ultima risposta o se c'è un post senza risposte dell'post stesso)
in tutto questo ci devono essere anche le room vuote...

io ho provato e riprovato
per ora la mia parte funzionante è questa
codice:
SELECT rooms.room, COUNT( post.id_room ) , MAX( post.data )
FROM
post
JOIN rooms ON post.id_room = rooms.id_room
GROUP BY post.id_room


che ne dite???
1.976 messaggi dal 27 luglio 2005
Contributi
salve,
non so se puo' andare bene, ma in SQL Server io userei un po' di common table expression per pre-confezionare alcune info...
in maniera triviale scriverei probabilmente qualche cosa simile a
SET NOCOUNT ON;
GO
USE tempdb;
GO
CREATE TABLE dbo.Rooms (
  Id int NOT NULL PRIMARY KEY,
  Room varchar(10) NOT NULL
  );
CREATE TABLE dbo.Utenti (
  Id int NOT NULL PRIMARY KEY,
  Nome varchar(10) NOT NULL,
  Cognome varchar(10) NOT NULL
  );
CREATE TABLE dbo.Post (
  Id_Utente int NOT NULL,
  Id_Post int NOT NULL IDENTITY PRIMARY KEY,
  Titolo varchar(10) NOT NULL,
  Testo varchar(10) NOT NULL,
  Id_Room int NOT NULL,
  Data datetime NOT NULL
  );
CREATE TABLE dbo.Risposte (
  Id_Utente int NOT NULL,
  Id_Risposta int NOT NULL IDENTITY PRIMARY KEY,
  Id_Post int NOT NULL ,
  Titolo varchar(10) NOT NULL,
  Testo varchar(10) NOT NULL,
  Id_Room int NOT NULL,
  Data datetime NOT NULL
  );  
GO
INSERT INTO dbo.Rooms 
  VALUES ( 1, 'SQL' ), ( 2, 'Asp' ), ( 3, 'Sys' ), ( 4, 'Test' );
INSERT INTO dbo.Utenti
  VALUES ( 1, 'na', 'Rare' ), ( 2, 'Andrea', 'Montanari' ), ( 3, 'Daniele', 'Bochicchio' );
INSERT INTO dbo.Post
  VALUES ( 1, 'Titolo1', 'Testo1', 1, '20111210');
INSERT INTO dbo.Risposte
  VALUES ( 2, 1, 'Titolo1.1', 'Testo1.1', 1, '20111210 00:01');

INSERT INTO dbo.Post
  VALUES ( 2, 'Titolo2', 'Testo2', 2, '20111210 00:01');
INSERT INTO dbo.Risposte
  VALUES ( 1, 2, 'Titolo2.1', 'Testo2.1', 2, '20111210 00:01:05'),
      ( 3, 2, 'Titolo2.2', 'Testo2.2', 2, '20111210 00:01:10');

INSERT INTO dbo.Post
  VALUES ( 3, 'Titolo3', 'Testo3', 3, '20111210 00:01');

GO
    
WITH cteRPost AS (
  SELECT p.Id_Room, COUNT(*) AS [Count]
    , MAX(p.Data) AS [Data]
    FROM dbo.Post p
    GROUP BY p.Id_Room
  ),
cteRisp AS (
  SELECT p.Id_Room, COUNT(*) AS [Count]
    , MAX(p.Data) AS [Data]
    FROM dbo.Risposte p
    GROUP BY p.Id_Room
  )
SELECT r.Room
  , cp.[Count] AS [NDiscussioni]
  , cr.[Count] AS [NRisposte]
  , CASE WHEN cr.Data IS NULL THEN cp.Data ELSE cr.Data END AS [LastActivity]
  , CASE WHEN cr.Data IS NULL THEN
    (SELECT u.Cognome + ' ' + u.Nome AS [Utente]
      FROM dbo.Post post
        JOIN dbo.Utenti u ON u.Id = post.Id_Utente
      WHERE post.Data = cp.Data
        AND post.Id_Room = cp.Id_Room)
    ELSE
    (SELECT u.Cognome + ' ' + u.Nome AS [Utente]
      FROM dbo.Risposte post
        JOIN dbo.Utenti u ON u.Id = post.Id_Utente
      WHERE post.Data = cr.Data
        AND post.Id_Room = cr.Id_Room)    
    END AS [LastUser]
  FROM dbo.Rooms r
    LEFT JOIN cteRPost cp ON cp.Id_Room = r.Id
    LEFT JOIN cteRisp cr ON cr.Id_Room = r.Id
    LEFT JOIN dbo.Post p ON p.Data = cp.Data AND p.Id_Room = r.Id
    LEFT JOIN dbo.Risposte ri ON ri.Data = cr.Data AND ri.Id_Room = r.Id;
        
GO
DROP TABLE dbo.Post, dbo.Risposte, dbo.Rooms, dbo.Utenti;
--<---------------------
Room       NDiscussioni NRisposte   LastActivity            LastUser
---------- ------------ ----------- ----------------------- ---------------------
SQL        1            1           2011-12-10 00:01:00.000 Montanari Andrea
Asp        1            2           2011-12-10 00:01:10.000 Bochicchio Daniele
Sys        1            NULL        2011-12-10 00:01:00.000 Bochicchio Daniele
Test       NULL         NULL        NULL                    NULL



saluti

Andrea Montanari
http://www.hotelsole.com - http://www.hotelsole.com/asql/index.php
19 messaggi dal 19 dicembre 2011
no scusami ma non ho ben capito cosa e come hai fatto...


cmq ho provato a mettere il codice in phpmyadmin e non va...
mi da errore dopo il WITH.(da qui per capirci: "cteRPost AS[...]")

cmq facendo delle prove semplici, della serie:
WITH cteRPost(post.id_room) 
AS (
  SELECT post.id_room
    FROM post
  )
SELECT * FROM cteRPost

non funziona...
quindi credo proprio che il mysql 5 non supporti le CTE...

ti prego aiutami
Modificato da Rare il 20 dicembre 2011 09.25 -
42 messaggi dal 13 settembre 2007
Lo so è un pò lunga come query ma ho preferito evitare le CTE(se usi MySql per esempio, visto che non hai specificato il DB).
Ogni parte commentata può essere esternalizzata in una tabella temporanea (CTE o altro) e "joinata" in questa query.
Fammi sapere se è ok per te o se c'è qualche errore.

select  Rooms.id_room
,  ISNULL(NDiscussioni,0) as NDiscussioni
,  ISNULL(NRisposte,0) as NRisposte
,  max_post_data
,  nome_utente_post
,  max_risposta_data 
,  nome_utente_risposta
,  (case when ISNULL(max_risposta_data,'1900-01-01') > ISNULL(max_post_data,'1900-01-01') then 'risposta' else 'post' end) as last_activity_type
,  (case when ISNULL(max_risposta_data,'1900-01-01') > ISNULL(max_post_data,'1900-01-01') then max_risposta_data else max_post_data end) as last_activity_data
,  (case when ISNULL(max_risposta_data,'1900-01-01') > ISNULL(max_post_data,'1900-01-01') then nome_utente_risposta else nome_utente_post end) as last_activity_user
from  Rooms
/*recupero il numero di discussioni*/
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
 /*recupero il numero di risposte*/
 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
 /*recupero i dati dell'ultimo post*/
 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 ogni stanza recupero l'ultimo post*/
            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
             )
 )  as post_data
  on  Rooms.id_room = post_data.id_room
 /*recupero l'ultima risposta per 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 top 1 internal_risposta.id_risposta 
            from Risposte as internal_risposta 
            where external_risposta.id_post = internal_risposta.id_post
            order by internal_risposta.data desc
             )
 )  as risposta_data
  on  post_data.id_post = risposta_data.id_post


Modificato da roland79 il 20 dicembre 2011 12.05 -
19 messaggi dal 19 dicembre 2011
ho fatto un semplice copia e incolla del tuo codice...
come primo errore mi dava che non riconosceva ISNULL quindi l'ho separato e adesso:

#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 'IS NULL(NDiscussioni,0) as NDiscussioni , IS NULL(NRisposte,0) as NRisposte , ' at line 2

quindi proprio a inizio codice

cmq come ho modificato la precedente risposta:
ho fatto delle prove semplici, della serie:
WITH cteRPost(post.id_room) 
AS (
  SELECT post.id_room
    FROM post
  )
SELECT * FROM cteRPost


non funziona...
ma MySQL 5 supporta le CTE???
42 messaggi dal 13 settembre 2007
Scusami ho scritto CRT ma in realtà è CTE (common table expressions) :). Ho corretto il precedente post.

MySql mi sa che non supporta le CTE.
La funzione ISNULL è di SqlServer (non avevi specificato che si trattava di MySql)...
Comunque puoi vedere la documentazione qui per MySql:
http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_isnull

Visto che non ti funziona ISNULL, toglilo e funziona tutto in quanto il resto è puro SQL

Ciao
Modificato da roland79 il 20 dicembre 2011 12.04 -
Modificato da roland79 il 20 dicembre 2011 12.06 -
19 messaggi dal 19 dicembre 2011
select  Rooms.id_room
,  (NDiscussioni,0) as NDiscussioni
,  (NRisposte,0) as NRisposte
,  max_post_data
,  nome_utente_post
,  max_risposta_data 
,  nome_utente_risposta
,  (case when (max_risposta_data,'1900-01-01') > (max_post_data,'1900-01-01') then 'risposta' else 'post' end) as last_activity_type
,  (case when (max_risposta_data,'1900-01-01') > (max_post_data,'1900-01-01') then max_risposta_data else max_post_data end) as last_activity_data
,  (case when (max_risposta_data,'1900-01-01') > (max_post_data,'1900-01-01') then nome_utente_risposta else nome_utente_post end) as last_activity_user
from  Rooms
/*recupero il numero di discussioni*/
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
 /*recupero il numero di risposte*/
 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
 /*recupero i dati dell'ultimo post*/
 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 ogni stanza recupero l'ultimo post*/
            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
             )
 )  as post_data
  on  Rooms.id_room = post_data.id_room
 /*recupero l'ultima risposta per 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 top 1 internal_risposta.id_risposta 
            from Risposte as internal_risposta 
            where external_risposta.id_post = internal_risposta.id_post
            order by internal_risposta.data desc
             )
 )  as risposta_data
  on  post_data.id_post = risposta_data.id_post


senza ISNULL mi da questo 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

mmm....
42 messaggi dal 13 settembre 2007
In MySql al posto di ISNULL metti IfNULL e dovrebbe andarti.
Non conoscendo MySql e non avendo l'opportunità di testarlo, vado a spanne:
(case when ISNULL(max_risposta_data,'1900-01-01') > ISNULL(max_post_data,'1900-01-01') then 'risposta' else 'post' end) 

diventa
(case when IfNULL(max_risposta_data,'1900-01-01') > IfNULL(max_post_data,'1900-01-01') then 'risposta' else 'post' end case)  



Comunque non devi togliere solo ISNULL nel caso tu non lo voglia usare, ma tutta l'istruzione!
Ad esempio:
ISNULL(max_risposta_data,'1900-01-01')

diventa
max_risposta_data


Ti posto il link ufficiale di MySql5.0
http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html#function_ifnull
Modificato da roland79 il 21 dicembre 2011 09.07 -
Modificato da roland79 il 21 dicembre 2011 09.08 -

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.