Problema con ID query

venerdì 27 maggio 2011 - 17.28
Tag Elenco Tags  MySQL 5.5

dotnetnapo Profilo | Junior Member

Ciao a tutti,
vi riespongo un problema già sollevato di cui ho trovato una soluzione ma poco performante la quale diventa molto ingarbugliata con query complesse...
Il problema è il seguente:

TABELLA

ID - NUMERO
1 - 999
2 - 888
3 - 111

Se vado a fare la query ricercando il minimo numero,

SELECT
test.ID,
Min(test.Numero)
FROM
test

la query risultante è 1 - 111 e non 3 - 111 come dovrebbe essere

Come si risolve questo problema?

Grazie

lbenaglia Profilo | Guru

>Se vado a fare la query ricercando il minimo numero,
>
>SELECT
>test.ID,
>Min(test.Numero)
>FROM
>test
>
>la query risultante è 1 - 111 e non 3 - 111 come dovrebbe essere

Ciao,

Che DBMS utilizzi? Quella query non è corretta dal punto di vista sintattico in quanto per definizione occorre specificare la clausola GROUP BY con tutte le colonne della select list alle quali non hai applicato una funzione di aggregazione.
SQL Server ad esempio restituisce il seguente errore:

Msg 8120, Level 16, State 1, Line 1
Column 'dbo.foo.ID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

Per risolvere il tuo problema è sufficiente appoggiarsi ad una tabella derivata. In questo esempio per SQL Server 2008 farò uso di una CTE:

USE tempdb; CREATE TABLE dbo.foo( ID int NOT NULL, Numero int NOT NULL ); INSERT dbo.foo VALUES (1, 999), (2, 888), (3, 111); WITH CTE_GetMinValue(Numero) AS ( SELECT MIN(Numero) FROM dbo.foo ) SELECT F.* FROM dbo.foo AS F JOIN CTE_GetMinValue AS CTE ON F.Numero = CTE.Numero; /* Output: ID Numero ----------- ----------- 3 111 (1 row(s) affected) */ DROP TABLE dbo.foo;

>Grazie
Prego.

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

dotnetnapo Profilo | Junior Member

Sto utilizzando mysql, ma il problema esiste anche con il group, in pratica la funzione min prende il primo ID esempio

ID TIPO NUMMERO
1 rosso 444
2 rosso 333
3 verde 666
4 verde 555

SELECT
test.ID,
test.Tipo,
Min(test.Numero) AS Num
FROM
test
GROUP BY
test.Tipo

facendo una query con min su numero e group su tipo restituisce

1 - rosso 333
3 - verde 555

Impossibile da usare

Ho risolto con questa query

SELECT F.ID, F.IDTIPO, F.NUMERO
FROM test AS F
INNER JOIN (SELECT IDTIPO, MIN(NUMERO) AS NUMERO
FROM test
GROUP BY IDTIPO) AS Q
ON F.IDTIPO = Q.IDTIPO
AND F.NUMERO = Q.NUMERO

ma è un casino con query complesse... possibile che una cosa così banale si debba risolvere in qs modo?

lbenaglia Profilo | Guru

>Sto utilizzando mysql, ma il problema esiste anche con il group,
>in pratica la funzione min prende il primo ID esempio
>
>ID TIPO NUMMERO
>1 rosso 444
>2 rosso 333
>3 verde 666
>4 verde 555
>
>SELECT
>test.ID,
>test.Tipo,
>Min(test.Numero) AS Num
>FROM
>test
>GROUP BY
>test.Tipo
>
>facendo una query con min su numero e group su tipo restituisce
>
>1 - rosso 333
>3 - verde 555

Non utilizzo MySQL ma logicamente la query non è corretta se non si raggruppa anche per ID.

>Impossibile da usare
>
>Ho risolto con questa query
>
>SELECT F.ID, F.IDTIPO, F.NUMERO
>FROM test AS F
>INNER JOIN (SELECT IDTIPO, MIN(NUMERO) AS NUMERO
>FROM test
>GROUP BY IDTIPO) AS Q
>ON F.IDTIPO = Q.IDTIPO
>AND F.NUMERO = Q.NUMERO
>
>ma è un casino con query complesse... possibile che una cosa
>così banale si debba risolvere in qs modo?
Guarda che la query è banale ed è estremamente chiara dal punto di vista logico.

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

dotnetnapo Profilo | Junior Member

Andrò avanti con questa soluzione ma mi sembra assurdo dover fare questo giro vizioso per tirare fuori un ID che appartiene di fatto al numero minimo, non esidte qualche funzione che tira fuori l'ID esatto?

lbenaglia Profilo | Guru

>Andrò avanti con questa soluzione ma mi sembra assurdo dover
>fare questo giro vizioso per tirare fuori un ID che appartiene
>di fatto al numero minimo, non esidte qualche funzione che tira
>fuori l'ID esatto?
Se poni questa domanda mi sembra di capire che non ti sono chiare le funzioni di aggregazione e la clausola GROUP BY.
Prova ad approfondire questi argomenti sulla guida in linea di MySQL.

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

dotnetnapo Profilo | Junior Member

A me sembra di capire che la funzione di aggregazione cozza con la funzione min, e ti faccio un esempio concreto su cui mi sto sbattendo.
Ho circa 300 viaggi in database ogni viaggio ha circa 10 date di partenza annuali ognuna con prezzi variabili in base alle stagionalità.
Se vado a trovare di ognuno di questi viaggi le date con prezzo minimo ecco qui che la funzione di aggregazione non mi sembra che funzioni con min, in quanto mi tira fuori il prezzo minimo del viaggio ma la data non corrisponde

comunque non voglio sindacare oltre ....

grazie lo stesso

ugk111 Profilo | Junior Member

salve scusate se mi intrometto ma partendo dal tuo esempio ho provato con due semplici query e a me restituisce quanto da te richiesto quindi la prima query
SELECT Min(Tabella1.tipo) AS MinDitipo, Min(Tabella1.numero) AS MinDinumero
FROM Tabella1;
poi ho creato una seconda query
SELECT Tabella1.id, Tabella1.tipo, [Tabella1 Query].MinDinumero
FROM Tabella1 INNER JOIN [Tabella1 Query] ON Tabella1.numero = [Tabella1 Query].MinDinumero;
quindi facendo partire solo la seconda query restituisce il valore 3 - 111
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-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5