Principale utente con più risposte
Estrazione raggruppata particolare

Domanda
-
Ciao a tutti,
ho una Select di join su varie tabelle che mi restituisce qualcosa del tipo:
Data - Ordinale - Prezzo - Costo00:15:00 - 0 - 55 - 24
00:15:00 - 1 - 57 - 25
00:30:00 - 0 - 55 - 24
00:45:00 - 5 - 64 - 34
00:45:00 - 6 - 65 - 34
00:45:00 - 7 - 75 - 35In questo resultset ci possono essere delle ore duplicate: ci sono 2 record per il blocco delle ore 00:15
uno solo per le 00:30 e tre per le 00:45.Dovrei estrarre solo un record per ogni blocco di ora, che abbia il Max(ordinale), ma poi recuperare anche le altre colonne.
Se faccio un GroupBy per le ora e uso il Max per l'ordinale, non posso poi recuperare gli altri valori.
Come posso risolvere questo problema?
Grazie
Luigi
PS
Questi campi non fanno parte di una tabella fisica, ma solo il result set di una SELECT abbastanza complessa che opera in Join su più tabelle.- Modificato Ciupaz venerdì 7 ottobre 2011 14:15
Risposte
-
Dovrei estrarre solo un record per ogni blocco di ora, che abbia il Max(ordinale), ma poi recuperare anche le altre colonne.
...
PS
Questi campi non fanno parte di una tabella fisica, ma solo il result set di una SELECT abbastanza complessa che opera in Join su più tabelle.Ciao Luis,
Che sia una tabella fisica o una query complessa la situazione non cambia, devi sempre passare da una tabella derivata che restituisca la tua chiave di interrogazione (Data e Ordinale più alto) da mettere in JOIN con la tabella/query come nel seguente esempio:
USE tempdb; CREATE TABLE dbo.foo( Data time NOT NULL, Ordinale tinyint NOT NULL, Prezzo tinyint NOT NULL, Costo tinyint NOT NULL ) INSERT dbo.foo VALUES ('00:15:00', 0, 55, 24) , ('00:15:00', 1, 57, 25) , ('00:30:00', 0, 55, 24) , ('00:45:00', 5, 64, 34) , ('00:45:00', 6, 65, 34) , ('00:45:00', 7, 75, 35); WITH CTE_GetKey(Data, Ordinale) AS ( SELECT Data, MAX(Ordinale) FROM dbo.foo GROUP BY Data ) SELECT F.* FROM dbo.foo AS F JOIN CTE_GetKey AS C ON F.Data = C.Data AND F.Ordinale = C.Ordinale ORDER BY F.Data; /* Output: Data Ordinale Prezzo Costo ---------------- -------- ------ ----- 00:15:00.0000000 1 57 25 00:30:00.0000000 0 55 24 00:45:00.0000000 7 75 35 (3 row(s) affected) */ DROP TABLE dbo.foo;
Ciao!
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo
http://social.technet.microsoft.com/Forums/it-IT/sqlserverit- Contrassegnato come risposta Ciupaz venerdì 7 ottobre 2011 14:34
-
Sì lo so cosa dicono i BOL, la mia era solo un'osservazione "filosofica", nel senso che mi sembrava una carenza intrinseca del SQL il fatto di non poter recuperare anche le altre colonne (non appartenenti al Group By), dato che comunque il motore relazionale ha già recuperato i record che soddisfano la condizione. Tutto qua.
Perdonami Luis,
Ma non sono d'accordo. :-)
Tu hai scritto: "Dovrei estrarre solo un record per ogni blocco di ora, che abbia il Max(ordinale), ma poi recuperare anche le altre colonne".
Come fai raggruppare per ogni ora e Max(ordinale) e nel contempo ottenere anche le altre colonne? E' logicamente impossibile dato che se vuoi recuperare anche le altre colonne dovrai specificarle nella SELECT list e nella clausola GROUP BY, non ottenendo quindi il risultato che chiedi.
Ciao!
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo
http://social.technet.microsoft.com/Forums/it-IT/sqlserverit- Contrassegnato come risposta Ciupaz lunedì 10 ottobre 2011 07:43
Tutte le risposte
-
Dovrei estrarre solo un record per ogni blocco di ora, che abbia il Max(ordinale), ma poi recuperare anche le altre colonne.
...
PS
Questi campi non fanno parte di una tabella fisica, ma solo il result set di una SELECT abbastanza complessa che opera in Join su più tabelle.Ciao Luis,
Che sia una tabella fisica o una query complessa la situazione non cambia, devi sempre passare da una tabella derivata che restituisca la tua chiave di interrogazione (Data e Ordinale più alto) da mettere in JOIN con la tabella/query come nel seguente esempio:
USE tempdb; CREATE TABLE dbo.foo( Data time NOT NULL, Ordinale tinyint NOT NULL, Prezzo tinyint NOT NULL, Costo tinyint NOT NULL ) INSERT dbo.foo VALUES ('00:15:00', 0, 55, 24) , ('00:15:00', 1, 57, 25) , ('00:30:00', 0, 55, 24) , ('00:45:00', 5, 64, 34) , ('00:45:00', 6, 65, 34) , ('00:45:00', 7, 75, 35); WITH CTE_GetKey(Data, Ordinale) AS ( SELECT Data, MAX(Ordinale) FROM dbo.foo GROUP BY Data ) SELECT F.* FROM dbo.foo AS F JOIN CTE_GetKey AS C ON F.Data = C.Data AND F.Ordinale = C.Ordinale ORDER BY F.Data; /* Output: Data Ordinale Prezzo Costo ---------------- -------- ------ ----- 00:15:00.0000000 1 57 25 00:30:00.0000000 0 55 24 00:45:00.0000000 7 75 35 (3 row(s) affected) */ DROP TABLE dbo.foo;
Ciao!
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo
http://social.technet.microsoft.com/Forums/it-IT/sqlserverit- Contrassegnato come risposta Ciupaz venerdì 7 ottobre 2011 14:34
-
-
Ma non è un limite del SQL il fatto di non potersi "portare appresso" anche gli altri campi quando effettuo una funzione di raggruppamento?
Alla fin fine deve comunque individuare le righe che mi deve restituire, e cosa ci vorrebbe a darmi anche gli altri campi di queste stesse righe?
L
-
Ma non è un limite del SQL il fatto di non potersi "portare appresso" anche gli altri campi quando effettuo una funzione di raggruppamento?
Alla fin fine deve comunque individuare le righe che mi deve restituire, e cosa ci vorrebbe a darmi anche gli altri campi di queste stesse righe?
No, non è una limitazione di SQL Server. Il discorso è molto semplice, basta leggere la documentazione della clausola GROUP BY, in particolare: Each table or view column in any nonaggregate expression in the <select> list must be included in the GROUP BY listIn altre parole, tutte le colonne specificate nel comando di SELECT sulle quali non sono applicate funzioni di aggregazione DEVONO essere specificate nella clausola GROUP BY.
Ora, come pensi di ottenere il risultato richiesto senza ricorrere ad una tabella derivata? :-)
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo
http://social.technet.microsoft.com/Forums/it-IT/sqlserverit -
Sì lo so cosa dicono i BOL, la mia era solo un'osservazione "filosofica", nel senso che mi sembrava una carenza intrinseca del SQL il fatto di non poter recuperare anche le altre colonne (non appartenenti al Group By), dato che comunque il motore relazionale ha già recuperato i record che soddisfano la condizione. Tutto qua.
E questa mancanza, come giustamente hai segnalato tu, fa sì che bisogna ricorrere a tabelle derivate per raggiungere lo scopo di questo post.
Luigi -
Sì lo so cosa dicono i BOL, la mia era solo un'osservazione "filosofica", nel senso che mi sembrava una carenza intrinseca del SQL il fatto di non poter recuperare anche le altre colonne (non appartenenti al Group By), dato che comunque il motore relazionale ha già recuperato i record che soddisfano la condizione. Tutto qua.
Perdonami Luis,
Ma non sono d'accordo. :-)
Tu hai scritto: "Dovrei estrarre solo un record per ogni blocco di ora, che abbia il Max(ordinale), ma poi recuperare anche le altre colonne".
Come fai raggruppare per ogni ora e Max(ordinale) e nel contempo ottenere anche le altre colonne? E' logicamente impossibile dato che se vuoi recuperare anche le altre colonne dovrai specificarle nella SELECT list e nella clausola GROUP BY, non ottenendo quindi il risultato che chiedi.
Ciao!
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo
http://social.technet.microsoft.com/Forums/it-IT/sqlserverit- Contrassegnato come risposta Ciupaz lunedì 10 ottobre 2011 07:43