Newsgroup: it.comp.software.database
Titolo: Sintassi SQL

Ho una query del tipo
SELECT CAMPO1, CAMPO2, SUM(valore) AS TOT FROM TABELLA GROUP BY CAMPO1,
CAMPO2
Adesso io vorrei che nel risultato della query comparisse anche il primo
valore trovato nel campo3. In access potevo usare la sintassi FIRST(campo3)
con SQL server 2K come si puň fare?
Ciao e grazie.
NB: L'unica soluzione che mi č venuta in mente č una funzione che in base ai
valori passati (campo1, campo2) restituisca il valore desiderato. Cosě
facendo ottengo il risultato voluto, ma in termini di prestazioni mi sembra
una ciofeca.

 con SQL server 2K come si può fare?
sotto mssql server c'e' TOP, ma l'hosempre usata a livello select e non
campo devi provare; alternativa direi una subquery che estragga prima il
record di campo3 (xche' campo3? e' un terzo o errore di stompa fu?)

 record di campo3 (xche' campo3? e' un terzo o errore di stompa fu?)
mi sembra che TOP non sia utilizzabile con le funzioni di aggregazione. Per
spiegarmi meglio.
Tabella:
campo1  campo2      campo3
  1             5,00     05/06/2003
  1             3,00     04/05/2003
  1             2,00     02/09/2003
il risultato che cerco è raggruppare per campo1, sommare i valori di campo2
e recuperare la data più bassa di campo3 (ovviamente relativa al
raggruppamento campo1).
Come dicevo prima se creo una funzione (es. cerca_campo3) che in base a
campo1 ricerca la data che mi interessa potrei fare una select del tipo:
SELECT SUM(campo2), cerca_campo3(campo1) FROM tabella GROUP BY campo1.
In questa maniera ottengo il risultato voluto. Ma viene effettuata una
select per ogni riga trovata nella prima select. Insomma le prestazioni
lasciano molto a desiderare.
Ciao,

 al raggruppamento campo1).
Ciao Selvad,
se ho capito bene la tua domanda puoi ottenere il risultato richiesto con
una semplice GROUP BY.
Ti allego un esempio:
USE tempdb
GO
/* Definisco la tabella dbo.Tabella */
CREATE TABLE dbo.Tabella(
Campo1 int NOT NULL,
Campo2 smallmoney NOT NULL,
Campo3 smalldatetime NOT NULL
)
GO
/* La popolo */
SET NOCOUNT ON
INSERT dbo.Tabella VALUES(1, 5.00,'20030605')
INSERT dbo.Tabella VALUES(1, 3.00,'20030504')
INSERT dbo.Tabella VALUES(1, 2.00,'20030902')
INSERT dbo.Tabella VALUES(2, 15.00,'20020927')
INSERT dbo.Tabella VALUES(2, 14.04,'20011206')
INSERT dbo.Tabella VALUES(2, 21.21,'20030929')
INSERT dbo.Tabella VALUES(3, 28.10,'20030131')
INSERT dbo.Tabella VALUES(4, 33.14,'20020224')
INSERT dbo.Tabella VALUES(4, 121.90,'20020606')
INSERT dbo.Tabella VALUES(4, 179.3625,'20020709')
SET NOCOUNT OFF
GO
/* Query */
SELECT Campo1, SUM(Campo2) Totale, MIN(Campo3) Data
FROM dbo.Tabella
GROUP BY Campo1
ORDER BY Campo1
GO
/* Output:
Campo1      Totale                Data
----------- --------------------- --------------------
1           10.0000               2003-05-04 00:00:00
2           50.2500               2001-12-06 00:00:00
3           28.1000               2003-01-31 00:00:00
4           334.4025              2002-02-24 00:00:00
(4 row(s) affected)
*/
/* Pulizia */
DROP TABLE dbo.Tabella
Ciao!
-- 
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://mvp.support.microsoft.com
http://italy.mvps.org

 GO
Purtroppo per semplificare il messaggio ho fatto un esempio incompleto e
sbagliato. In realtà a me non serve il valore minimo del campo3. Mi serve il
primo valore trovato rispetto all'ordinamento di un campo (che generalmente
non fa parte del gruppo GROUP BY).
Per rimanere all'esempio che mi hai proposto dovrei aggiungere un campo4, e
ottenere nella query il valore del campo4 corrispondente alla data minima.
Che tu sappia è possibile mediante sintassi SQL?
Ciao e grazie.

 Ciao e grazie.
Prego.



Ho modificato il tuo esempio, aggiungendo campo4. Poi ho creato la funzione
che mi permette di ottenere i risultati desiderati. Infine ho modificato la
query finale, utilizzando la funzione appena creata. In questa maniera tutto
funziona, ma le prestazioni non sono ottimali. Speravo che vi fosse una
maniera per migliorare le prestazioni.
Nel campo 4 vengono inseriti valori a caso. Con questo intendo dire che
nessun tipo di ordinamento sul campo4 riesce a determinare quali sono i
valori da considerare. Il valore che mi interessa è sempre quello relativo
alla data (campo3) più bassa.
Spero di essere riuscito a spiegarmi meglio.
Ciao .
USE tempdb
GO
/* Definisco la tabella dbo.Tabella */
CREATE TABLE dbo.Tabella(
Campo1 int NOT NULL,
Campo2 smallmoney NOT NULL,
Campo3 smalldatetime NOT NULL,
campo4 varchar(10)
)
GO
/* La popolo */
SET NOCOUNT ON
INSERT dbo.Tabella VALUES(1, 5.00,'20030605', 'nota')
INSERT dbo.Tabella VALUES(1, 3.00,'20030504', 'ciao')
INSERT dbo.Tabella VALUES(1, 2.00,'20030902', 'prova')
INSERT dbo.Tabella VALUES(2, 15.00,'20020927', 'testo')
INSERT dbo.Tabella VALUES(2, 14.04,'20011206', 'xxxx')
INSERT dbo.Tabella VALUES(2, 21.21,'20030929', 'yyyy')
INSERT dbo.Tabella VALUES(3, 28.10,'20030131', 'iiii')
INSERT dbo.Tabella VALUES(4, 33.14,'20020224', 'rrrr')
INSERT dbo.Tabella VALUES(4, 121.90,'20020606', 'ffff')
INSERT dbo.Tabella VALUES(4, 179.3625,'20020709', 'pppp')
SET NOCOUNT OFF
GO
CREATE FUNCTION dbo.CercaCampo4(@Chiave varchar(10))
RETURNS varchar(10) AS
BEGIN
 declare @tmp varchar(10)
 SELECT TOP 1 @tmp=campo4 FROM dbo.Tabella
 WHERE campo1=@Chiave
 ORDER BY campo3
RETURN @tmp
END
GO
/* Query */
SELECT Campo1, SUM(Campo2) Totale, dbo.CercaCampo4(campo1)
FROM dbo.Tabella
GROUP BY Campo1
ORDER BY Campo1
GO
Risultati:
Campo1      Totale                note
----------- --------------------- ---------- 
1           10.0000               ciao
2           50.2500               xxxx
3           28.1000               iiii
4           334.4025              rrrr
/* Pulizia */
DROP TABLE dbo.Tabella
DROP FUNCTION dbo.CercaCampo4

Non so se ho capito, e mi sa tanto che la query che ho scritto mi e' venuto
un "brodolone" sia dal punto di vista dello stile che della performance, ma
sembra funzionare... ho modificato qualche riga dei post precedenti, cioe'
ho sfruttato il lavoro altrui :)
USE tempdb
GO
/* Definisco la tabella dbo.Tabella */
CREATE TABLE dbo.Tabella(
Campo1 int NOT NULL,
Campo2 smallmoney NOT NULL,
Campo3 smalldatetime NOT NULL,
Campo4 varchar(15) NOT NULL
)
GO
/* La popolo */
SET NOCOUNT ON
INSERT dbo.Tabella VALUES(1, 5.00,'20030605','valore1')
INSERT dbo.Tabella VALUES(1, 3.00,'20030504','valore2')
INSERT dbo.Tabella VALUES(1, 2.00,'20030902','valore3')
INSERT dbo.Tabella VALUES(2, 15.00,'20020927','valore4')
INSERT dbo.Tabella VALUES(2, 14.04,'20011206','valore5')
INSERT dbo.Tabella VALUES(2, 21.21,'20030929','valore6')
INSERT dbo.Tabella VALUES(3, 28.10,'20030131','valore7')
INSERT dbo.Tabella VALUES(4, 33.14,'20020224','valore8')
INSERT dbo.Tabella VALUES(4, 121.90,'20020606','valore9')
INSERT dbo.Tabella VALUES(4, 179.3625,'20020709','valore10')
SET NOCOUNT OFF
GO
/* Query */
select t2.Campo1, Totale,Data,valore_min
from
(select Campo1, Campo3, Campo4 valore_min from dbo.Tabella) as t1
inner join
(SELECT Campo1, SUM(Campo2) Totale, MIN(Campo3) Data FROM dbo.Tabella GROUP
BY Campo1) as t2
on t2.Data = t1.Campo3 and t1.Campo1=t2.Campo1
GO
/* Output:
Campo1 Totale Data Valore_min
------- ------------ ---------------------- ---------------
1 10.0000 2003-05-04 00:00:00 valore2
2 50.2500 2001-12-06 00:00:00 valore5
3 28.1000 2003-01-31 00:00:00 valore7
4 334.4025 2002-02-24 00:00:00 valore8
(4 row(s) affected)
*/
/* Pulizia */
DROP TABLE dbo.Tabella
Paulus
--------------------------------
Inviato via 
http://usenet.libero.it

 Spero di essere riuscito a spiegarmi meglio.
Ciao Selvad,
si, ora credo di aver capito. :-)
Prova a vedere se la seguente query può andare:
/* Query */
SELECT T1.Campo1, T1.Totale, T2.Campo4 Note
FROM (
    SELECT Campo1, SUM(Campo2) Totale, MIN(Campo3) Campo3ASC
    FROM dbo.Tabella
    GROUP BY Campo1) T1 JOIN dbo.Tabella T2
ON T1.Campo1 = T2.Campo1
AND T1.Campo3ASC = T2.Campo3
ORDER BY T1.Campo1
/* Output:
Campo1      Totale                Note
----------- --------------------- ---------- 
1           10.0000               ciao
2           50.2500               xxxx
3           28.1000               iiii
4           334.4025              rrrr
(4 row(s) affected)
*/
Come puoi notare, nella subquery T1 calcolo il MIN di Campo3 raggruppando
per Campo1. Questo equivale alla tua TOP 1 con ordinamento ascendente per
Campo3.
A questo punto faccio una INNER JOIN con la tabella originale (T2) sulle
colonne Campo1 e Campo3.



Ho provato la tua soluzione e quella di Paulus, che praticamente sono molto
simili. Vi ringrazio cosě ottengo i risultati desiderati, ed a guardare la
traccia di esecuzione sul server, le prestazioni sembrano migliorare
notevolmente.
Ciao.