salve,
symonx80 wrote:
Ciao,
ho bisogno di una mano nel realizzare una query.Devo estrarre, da una tabella contenente le letture dei contatori elettrici, gli utenti che hanno la stessa lettura da più di due anni.
La tabella in questione è la seguente
TB_LETTURE(COD_CONTATORE,DATA_LETTURA,QTA_LETTURA,CONSUMO,STATO_CONTATORE, ANNO_INSERIMENTO_CONTATORE)
Nel risultato finale non dovranno essere presenti gli utenti che hanno un contatore con STATO_CONTATORE'A' (aperto) da meno di due anni, nè quelli con STATO_CONTATORE 'C' (chiuso)
Qualcuno può darmi una mano?
Io ho pensato in un
SELECT COD_CONTATORE FROM TB_LETTURE WHERE STATO_CONTATORE='A' AND ANNO_INSERIMENTO_CONTATORE < 2009 AND
GROUP BY COD_CONTATORE
HAVING SUM(CONSUMO)=0
ma non mi pare la soluzione corretta in quanto in questo modo escludo dal risultato, ad esempio, gli utenti che hanno avuto letture differenti fino al 01/01/2008 e poi la stessa lettura da quella data in avanti.
Grazie
in queste esposizioni e' sinceramente necessario definire meglio lo scenario, quindi fornire i comandi CREATE TABLE corretti ed un minimo di dati per la popolazione iniziale tramite opportuni comandi INSERT INTO al fine di non richiedere da parte di chi vorrebbe aiutare anche la necessita' di sprecare tempo cercando di ricostruire, appunto, uno scenario sconosciuto... e' anche solitamente indicato esplicitare il motore SQL utilizzato

al di la' di cio', potrebbe forse essere interessante, in SQL Server 2005 o successivi, l'utilizzo di Common Table Expression al fine di produrre risultati logici intermedi da poter raffinare in successive operazioni.. ad esempio si potrebbe ragionare e codificare,
SET NOCOUNT ON;
USE tempdb;
GO
CREATE TABLE dbo.TB_LETTURE(
COD_CONTATORE int,
DATA_LETTURA datetime,
QTA_LETTURA decimal(18,4),
CONSUMO decimal(18,4),
STATO_CONTATORE char(1),
ANNO_INSERIMENTO_CONTATORE int
);
CREATE TABLE dbo.Utenti (
Id int NOT NULL,
Nome varchar(10),
COD_CONTATORE int
);
GO
INSERT INTO dbo.TB_LETTURE VALUES ( 1, '20070101', 1, 1, 'A', 2005 ); INSERT INTO dbo.TB_LETTURE VALUES ( 1, '20071101', 1, 1, 'A', 2005 ); INSERT INTO dbo.TB_LETTURE VALUES ( 1, '20080101', 1, 1, 'A', 2005 ); INSERT INTO dbo.TB_LETTURE VALUES ( 1, '20081101', 1, 1, 'A', 2005 ); INSERT INTO dbo.TB_LETTURE VALUES ( 1, '20090101', 1, 1, 'A', 2005 ); INSERT INTO dbo.TB_LETTURE VALUES ( 1, '20091101', 1, 1, 'A', 2005 ); INSERT INTO dbo.TB_LETTURE VALUES ( 1, '20100101', 1, 1, 'A', 2005 );
INSERT INTO dbo.Utenti VALUES ( 1, 'Andrea', 1 );
GO
WITH cteGrouped AS (
SELECT t.COD_CONTATORE, SUM(t.CONSUMO) AS [Consumo Annuo], DATEPART( YYYY, t.DATA_LETTURA) AS [Anno]
FROM dbo.TB_LETTURE t
WHERE (
t.STATO_CONTATORE <> 'C'
AND (
t.STATO_CONTATORE = 'A'
AND t.ANNO_INSERIMENTO_CONTATORE < 2010
)
escludiamo anche l'anno corrente in quanto non terminato AND DATEPART(YYYY, t.DATA_LETTURA) < DATEPART(YYYY, GETDATE()) )
GROUP BY t.COD_CONTATORE, DATEPART( YYYY, t.DATA_LETTURA)
),
cteDifferenziali AS (
SELECT c.COD_CONTATORE, SUM(c.[Consumo Annuo]) AS [Globale], MIN(c.[Consumo Annuo]) AS [differenziale], COUNT(*) AS [y]
FROM cteGrouped c
GROUP BY c.COD_CONTATORE
HAVING SUM(c.[Consumo Annuo]) / COUNT(*) = MIN(c.[Consumo Annuo]) )
SELECT u.Id, u.Nome, c.COD_CONTATORE
FROM cteDifferenziali c
JOIN dbo.Utenti u ON u.COD_CONTATORE = c.COD_CONTATORE;
GO
DROP TABLE dbo.TB_LETTURE, dbo.Utenti;
dove abbiamo la prima cte che definisce il filtro iniziale di inclusione con preaggregazione a livello di anno solare, un successivo raggruppamento con evidenziazione del differenziale (MIN(consumo)) e del "numero di anni" di accorpamento.. essendo richiesto un consumo == per l'intero arco temporale, possiamo benissimo ridefinire l'espressione con una semplificazione matemetica quale:
somma aggregata negli anni / numero di anni = consumo minimo l'ultima proiezione invece si occupa di relazionare l'eventuale tabella utenti per ottenerne l'attributo da esporre al richiedente.. ma forse come ho inteso i dati o lo scenario non e' corretto rispetto alla tua vera richiesta..
saluti