Aiuto query particolare!

lunedì 23 marzo 2009 - 17.35

ventu Profilo | Newbie

Ciao a tutto il forum.
Sono disperato è tutto il giorno che batto la testa in questa query ma da solo, non riesco :(
Sto facendo una pagina asp che mi deve dare una somma di alcuni prodotti del mio magazino.
In un database sql (express) ho una tabella chiamata PENNE con alcuni dati cosi predisposti:

Prodotto Modello Revisione Costo

PENNA SFERA 1 10
PENNA SFERA 2 20
PENNA SFERA 0 15
PENNA STILO 2 10
PENNA STILO 1 13
PENNA REPLAY 0 10
PENNA REPLAY 1 11

Allora il punto è questo. Io devo avere la somma del costo delle penne(SFERA+STILO+REPLAY) ma con la rev massima. Quindi la somma solo di queste righe:

Prodotto Modello Revisione Costo
PENNA SFERA 2 20
PENNA STILO 2 10
PENNA REPLAY 1 11

SOMMA TOTALE= 41

Tutto il resto (ossia le revisioni minori) non devono essere calcolate nella somma totale.
Vi ringrazio enormemente già da subito qualora mi possiate aiutare!

lbenaglia Profilo | Guru

>Allora il punto è questo. Io devo avere la somma del costo delle
>penne(SFERA+STILO+REPLAY) ma con la rev massima. Quindi la somma
>solo di queste righe:
>
>Prodotto Modello Revisione Costo
>PENNA SFERA 2 20
>PENNA STILO 2 10
>PENNA REPLAY 1 11
>
>SOMMA TOTALE= 41

Ciao Marco,

Non ho capito quale result set vuoi ottenere.
Quello che hai scritto NON E' relazionale, pertanto non può essere restituito da una query.

Se vuoi solo il totale puoi utilizzare la seguente query:

USE tempdb; CREATE TABLE dbo.Prodotti( Prodotto varchar(5) NOT NULL, Modello varchar(6) NOT NULL, Revisione tinyint NOT NULL, Costo tinyint NOT NULL ); INSERT dbo.Prodotti VALUES ('PENNA', 'SFERA', 1, 10) , ('PENNA', 'SFERA', 2, 20) , ('PENNA', 'SFERA', 0, 15) , ('PENNA', 'STILO', 2, 10) , ('PENNA', 'STILO', 1, 13) , ('PENNA', 'REPLAY', 0, 10) , ('PENNA', 'REPLAY', 1, 11); WITH CTE_GetKey AS ( SELECT Prodotto, Modello, MAX(Revisione) AS Revisione FROM dbo.Prodotti GROUP BY Prodotto, Modello ) SELECT SUM(P.Costo) AS Totale FROM dbo.Prodotti AS P JOIN CTE_GetKey AS C ON P.Prodotto = C.Prodotto AND P.Modello = C.Modello AND P.Revisione = C.Revisione; /* Output: Totale ----------- 41 (1 row(s) affected) */ DROP TABLE dbo.Prodotti;

>Vi ringrazio enormemente già da subito qualora mi possiate aiutare!
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

ventu Profilo | Newbie

>CREATE TABLE dbo.Prodotti(
>Prodotto varchar(5) NOT NULL,
>Modello varchar(6) NOT NULL,
>Revisione tinyint NOT NULL,
>Costo tinyint NOT NULL
>);
>
>INSERT dbo.Prodotti VALUES
> ('PENNA', 'SFERA', 1, 10)
> , ('PENNA', 'SFERA', 2, 20)
> , ('PENNA', 'SFERA', 0, 15)
> , ('PENNA', 'STILO', 2, 10)
> , ('PENNA', 'STILO', 1, 13)
> , ('PENNA', 'REPLAY', 0, 10)
> , ('PENNA', 'REPLAY', 1, 11);
>
>WITH CTE_GetKey AS
>(
> SELECT Prodotto, Modello, MAX(Revisione) AS Revisione
> FROM dbo.Prodotti
> GROUP BY Prodotto, Modello
>)
>SELECT SUM(P.Costo) AS Totale
>FROM dbo.Prodotti AS P
>JOIN CTE_GetKey AS C
>ON P.Prodotto = C.Prodotto
>AND P.Modello = C.Modello
>AND P.Revisione = C.Revisione;
>

Ciao, come avrai inteso, sono un neofita di sql.
Volevo chiederti però come posso passare la variabile PENNA perchè nell'elenco che ti ho fatto ci sono solo PENNE ma in realtà ci sono tanti altri tipi di oggetti. PENNARELLI
Quindi, prendeno la variabile da una textbox devo passargli il parametro che devo richiedere (in questo caso PENNA)

grazie molte!

ventu Profilo | Newbie

Andando avanti con gli errori e provando le query con visual studio, sono arrivato a questo punto:

Ho messo i valori dei miei campi (che non sono penne) hehe

WITH CTE_GetKey AS (SELECT commessa, descrizione, MAX(rev) AS Expr1, importo, nsistemi, path AS rev
FROM prevcomm
GROUP BY commessa, descrizione, rev, importo, nsistemi, path)
SELECT SUM(P.importo) AS Totale
FROM prevcomm AS P INNER JOIN
CTE_GetKey AS C ON P.commessa = C.commessa AND P.descrizione = C.commessa AND P.rev = C.rev

Mi dà questo errore:

Messaggio di errore: Tipo di dati operando nchar non valido per l'operatore SUM.

lbenaglia Profilo | Guru

>Volevo chiederti però come posso passare la variabile PENNA perchè
>nell'elenco che ti ho fatto ci sono solo PENNE ma in realtà ci
>sono tanti altri tipi di oggetti.
Devi inserire una clausola WHERE nella CTE:

DECLARE @Prodotto varchar(5); SET @Prodotto = 'PENNA'; WITH CTE_GetKey AS ( SELECT Prodotto, Modello, MAX(Revisione) AS Revisione FROM dbo.Prodotti WHERE Prodotto = @Prodotto GROUP BY Prodotto, Modello ) SELECT SUM(P.Costo) AS Totale FROM dbo.Prodotti AS P JOIN CTE_GetKey AS C ON P.Prodotto = C.Prodotto AND P.Modello = C.Modello AND P.Revisione = C.Revisione;

>grazie molte!
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

lbenaglia Profilo | Guru


>WITH CTE_GetKey AS (SELECT commessa, descrizione, MAX(rev)
>AS Expr1, importo, nsistemi, path AS rev
>FROM prevcomm
>GROUP BY commessa, descrizione, rev, importo, nsistemi, path)
> SELECT SUM(P.importo) AS Totale
> FROM prevcomm AS P INNER JOIN
>CTE_GetKey AS C ON P.commessa = C.commessa AND P.descrizione
>= C.commessa AND P.rev = C.rev
>
>Mi dà questo errore:
>
>Messaggio di errore: Tipo di dati operando nchar non valido per
>l'operatore SUM.
Perché raggruppi anche per rev?
E' corretto inserire anche tutte le altre colonne nella query?
Che ne dici di postare la struttura REALE della tabella (CREATE TABLE), alcuni dati REALI (INSERT INTO) ed il result set REALE che vuoi ottenere con quei dati?

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

Anonimo Profilo | Senior Member

Così funziona, ciao.

select sum(b.costo) from ( select max(revisione) as revisione, modello from t_prova group by modello ) as a inner join t_prova as b on a.revisione=b.revisione and a.modello=b.modello

cambia solo il nome della tabella e il nome dei campi dove ritieni opportuno.

ventu Profilo | Newbie

con questo esempio


select sum(b.importo) from
(
select max(rev) as rev, commessa, descrizione
from prevcomm
group by descrizione
) as a
inner join prevcomm as b
on a.rev=b.rev and a.descrizione=b.descrizione and a.commessa=b.commessa

Non mi dà errori e mi viene fuori la somma corretta, però non ci sono solo le penne (commesse), devo passare il valore commessa (nell'esempio penna) quindi ho provato cosi

SELECT SUM(b.importo) AS Expr1
FROM (SELECT commessa, descrizione, MAX(rev) AS rev
FROM prevcomm
WHERE (commessa = [i-4041])
GROUP BY commessa, descrizione) AS a INNER JOIN
prevcomm AS b ON a.rev = b.rev AND a.descrizione = b.descrizione

Ma mi dà un errore: il nome della colonna 'i-4041' non è valido... Eppure esiste dentro alla colonna commessa record "i-4041".
Se fixo anche questo ho quasi fatto e non vi scoccio più hehe :)
Grazie Marco


Anonimo Profilo | Senior Member

Ecco a te:

select sum(b.costo) from ( select max(revisione) as revisione, modello, prodotto from t_prova group by prodotto, modello ) as a inner join t_prova as b on a.revisione=b.revisione and a.modello=b.modello and a.prodotto=b.prodotto

Spero sia ok.

lbenaglia Profilo | Guru

>Ecco a te:
>
>select sum(b.costo) from
>(
>select max(revisione) as revisione, modello, prodotto
>from t_prova
>group by prodotto, modello
>) as a
>inner join t_prova as b
>on a.revisione=b.revisione
>and a.modello=b.modello
>and a.prodotto=b.prodotto
>
>Spero sia ok.

Ciao Marco,

Che differenza vedi rispetto al precedente esempio basato su una CTE?
Entrambe utilizzano LA MEDESIMA tabella derivata...

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

Anonimo Profilo | Senior Member

Forse nessuna... sono sicuro che le tue soluzioni sono ottime, ma preferisco SQL standard cosidetto "da casa" di più facile interpretazione per tutti

lbenaglia Profilo | Guru

>SELECT SUM(b.importo) AS Expr1
>FROM (SELECT commessa, descrizione, MAX(rev) AS rev
> FROM prevcomm
> WHERE (commessa = [i-4041])
>GROUP BY commessa, descrizione) AS a INNER JOIN
>prevcomm AS b ON a.rev = b.rev AND a.descrizione = b.descrizione
>
>Ma mi dà un errore: il nome della colonna 'i-4041' non è valido...
>Eppure esiste dentro alla colonna commessa record "i-4041".
>Se fixo anche questo ho quasi fatto e non vi scoccio più hehe
>:)
I literal in formato stringa vanno racchiusi tra singoli apici, pertanto dovrai specificare:

WHERE commessa = 'i-4041'

Però in precedenza hai scritto che vuoi rendere parametrica la query e ti ho postato un esempio che definisce una variabile locale, la valorizza e la specifica nella clausola WHERE.
Volendo puoi racchiudere tutta la SELECT in una stored procedure parametrica che andrai a richiamare lato client specificando il valore per il parametro.
Purtroppo però non ho ancora capito se l'esempio postato in precedenza soddisfa o meno le tue esigenze.
Puoi fornirci i dati richiesti?

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

lbenaglia Profilo | Guru

>Forse nessuna...
Toglierei il forse dato che in fase di esecuzione le viste, le UDF Inline Table-Valued e le CTE vengono espanse nella corrispettiva tabella derivata

>sono sicuro che le tue soluzioni sono ottime,
>ma preferisco SQL standard cosidetto "da casa" di più facile
>interpretazione per tutti
Le CTE aderiscono allo standard ANSI SQL e aiutano enormemente la lettura di query particolarmente complesse.
Comunque è una questione di gusti, a parità di performance ognuno è libero di utilizzare la forma che preferisce

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

ventu Profilo | Newbie

SELECT SUM(b.importo) AS Expr1
FROM (SELECT MAX(a.rev) AS rev, descrizione, commessa
FROM pervcomm
GROUP BY commessa, descrizione) AS a INNER JOIN
pervcomm AS b ON a.rev = b.rev AND a.descrizione = b.descrizione AND a.commessa = b.commessa

Ciao raga, e grazie ancora.
Con questa query ricevo questo errore :(
Impossibile associare l'identificatore in più parti "a.rev"

So che stresso ma devo riuscire a risolvere questo maledetto problema ;(

ventu Profilo | Newbie

DECLARE @commessa varchar(20);
SET @commessa = 'I-4040';

WITH CTE_GetKey AS
(
SELECT commessa, desrizione, MAX(rev) AS rev
FROM pervcomm
WHERE commessa = @commessa
GROUP BY commessa, desrizione
)
SELECT SUM(P.importo) AS Totale
FROM pervcomm AS P
JOIN CTE_GetKey AS C
ON P.commessa = C.commessa
AND P.desrizione = C.desrizione
AND P.rev = C.rev;


Con questa sintassi mi dà il seguente errore: Il costrutto o l'istruzione SQL Dichiara cursore non è supportato.
Grazie raga.

lbenaglia Profilo | Guru

>Con questa sintassi mi dà il seguente errore: Il costrutto o
>l'istruzione SQL Dichiara cursore non è supportato.
Puoi postare il comando di CREATE TABLE ed alcune INSERT come ho fatto io in precedenza?

Ciao!

--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

lbenaglia Profilo | Guru

>Con questa query ricevo questo errore :(
>Impossibile associare l'identificatore in più parti "a.rev"

Sostituisci MAX(a.rev) con MAX(rev)

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

ventu Profilo | Newbie

SELECT SUM(b.importo) AS Expr1
FROM (SELECT MAX(rev) AS rev, descrizione, commessa
FROM pervcomm
GROUP BY commessa, descrizione) AS a INNER JOIN
pervcomm AS b ON a.rev = b.rev AND a.descrizione = b.descrizione AND a.commessa = b.commessa

Con questa non mi dà errori, però vorrei capire come passargli la ricerca su una certa commessa. Credo quindi, un parametro!
Es: I-4040

lbenaglia Profilo | Guru

>SELECT SUM(b.importo) AS Expr1
>FROM (SELECT MAX(rev) AS rev, descrizione, commessa
> FROM pervcomm
>GROUP BY commessa, descrizione) AS a INNER JOIN
>pervcomm AS b ON a.rev = b.rev AND a.descrizione = b.descrizione
>AND a.commessa = b.commessa
>
>Con questa non mi dà errori, però vorrei capire come passargli
>la ricerca su una certa commessa. Credo quindi, un parametro!
>Es: I-4040
Puoi postare il comando di CREATE TABLE ed alcune INSERT come ho fatto io in precedenza?

--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

ventu Profilo | Newbie

Ciao a tutti! Scusate se ieri sera vi ho abbandonato ma alle 24 sono crollato dal sonno :)
Stamani di buon ora mi sono alzato per concludere il mio lavoro e, ci sono riuscito! :) Ho aggiunto anche una piccola funzione alla query, la moltiplicazione del campo importo x la quantità. Posto l'intero codice nel caso in cui potesse servire a qualcuno.

SELECT SUM(b.importo * b.nsistemi) AS Expr1
FROM (SELECT commessa, descrizione, MAX(rev) AS rev
FROM prevcomm
WHERE (commessa = 'i-4041')
GROUP BY commessa, descrizione) AS a INNER JOIN
prevcomm AS b ON a.rev = b.rev AND a.descrizione = b.descrizione

==================================================

La parte in cui vedete: commessa = 'i-4041' era solo di test, in asp.net gli ho passato un cmd parameter divenendo cosi:
====================================
Protected Sub Button3_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim comm As String = TextBox1.Text
Dim sql As String = " SELECT SUM(b.importo * b.nsistemi) AS Expr1 FROM (SELECT commessa, descrizione, MAX(rev) AS rev FROM prevcomm WHERE (commessa = @commessa) GROUP BY commessa, descrizione) AS a INNER JOIN prevcomm AS b ON a.rev = b.rev AND a.descrizione = b.descrizione"
Dim cmd As New System.Data.SqlClient.SqlCommand(sql, cn)
cmd.Parameters.Add(New Data.SqlClient.SqlParameter("@commessa", comm))
cn.Open()
Dim dread As Data.SqlClient.SqlDataReader = cmd.ExecuteReader
dread.Read()
Dim totale As Long = dread.Item("Expr1")
End Sub
=============================================

Vorrei ringraziarvi di cuore, perchè senza di voi non avrei mai risolto in tempi non biblici :) Se passate dalla Toscana e volete assaggiare il vino buono e l'olio genuino mandatemi un PM! :)

Grazie! Mi rimetto al lavoro! Yup! :)

Marco
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5