none
Confronto campi sulla stessa tabella con trimestri differenti RRS feed

  • Domanda

  • Buon pomeriggio,

    sono impelagato in un problema teoricamente semplice da risolvere:

    ho una vista così strutturata [ID_Contratto],[RisparmioComplessivo],[Anno],[Trimestre];

    quello che vorrei realizzare è un confronto in base al trimestre precedente, ho quindi pensato di utilizzare una query tipo quella sotto riportata, che chiaramente no và...

    vi ringrazio in anticipo per qualsiasi suggerimento

    Stefano

    SELECT VP1.ID_Contratto, VP1.RisparmioComplessivo AS RisparmioTrimestre, VP2.ID_Contratto AS ID_Contratto2, VP2.RisparmioComplessivo AS RisparmioTrimestrePrec, VP1.Anno, VP1.Trimestre, VP2.Anno AS AnnoTP, VP2.Trimestre AS TrimestrePrec FROM vw_ViaggiRisparmioPeriodo as VP1 CROSS JOIN vw_ViaggiRisparmioPeriodo AS VP2 WHERE ((VP1.Trimestre<4 AND VP1.Trimestre=VP2.Trimestre-1 AND VP1.Anno=VP2.Anno) OR (VP1.Trimestre=4 AND VP2.TRIMESTRE=1 AND VP1.Anno = VP2.Anno-1)) AND (VP1.ID_Contratto = VP2.ID_Contratto)

    mercoledì 11 settembre 2013 15:54

Risposte

  • Buongiorno Stefano,

    supponendo l'analisi interna di un solo anno, ovvero di considerare i trimestri 1 a 4 in capo ad un anno unico, potresti modificare la query in questo modo:

    SELECT	VP1.ID_Contratto,
    		VP1.RisparmioComplessivo AS RisparmioTrimestre,
    		VP2.ID_Contratto AS ID_Contratto2,
    		VP2.RisparmioComplessivo AS RisparmioTrimestrePrec,
    		VP1.Anno,
    		VP1.Trimestre,
    		VP2.Anno AS AnnoTP,
    		VP2.Trimestre AS TrimestrePrec,
    		VP2.RisparmioComplessivo - VP1.RisparmioComplessivo AS DeltaRisparmio
    FROM	vw_ViaggiRisparmioPeriodo as VP1 LEFT JOIN vw_ViaggiRisparmioPeriodo AS VP2 ON VP1.ID_Contratto = VP2.ID_Contratto AND
                                                                                           VP1.Anno         = VP2.Anno         AND
                                                                                           VP1.Trimestre    = VP2.Trimestre + 1

    Rispetto alla tua query ho rivisto il JOIN, portandolo a LEFT (senza però gestire le casistiche NULL, quello va fatto come secondo step), e legando l'alias VP1 a VP2 sulla base di ID_Contratto, Anno, e Trimestre1 = Trimestre2 + 1

    Inoltre ho aggiunto un Delta automaticamente calcolato tra le due colonne RisparmioComplessivo.

    Fammi sapere se può andare, o se ci sono altre considerazioni da fare in merito.

    Buona giornata,


    Emiliano Musso

    giovedì 12 settembre 2013 06:42

Tutte le risposte

  • Buongiorno Stefano,

    supponendo l'analisi interna di un solo anno, ovvero di considerare i trimestri 1 a 4 in capo ad un anno unico, potresti modificare la query in questo modo:

    SELECT	VP1.ID_Contratto,
    		VP1.RisparmioComplessivo AS RisparmioTrimestre,
    		VP2.ID_Contratto AS ID_Contratto2,
    		VP2.RisparmioComplessivo AS RisparmioTrimestrePrec,
    		VP1.Anno,
    		VP1.Trimestre,
    		VP2.Anno AS AnnoTP,
    		VP2.Trimestre AS TrimestrePrec,
    		VP2.RisparmioComplessivo - VP1.RisparmioComplessivo AS DeltaRisparmio
    FROM	vw_ViaggiRisparmioPeriodo as VP1 LEFT JOIN vw_ViaggiRisparmioPeriodo AS VP2 ON VP1.ID_Contratto = VP2.ID_Contratto AND
                                                                                           VP1.Anno         = VP2.Anno         AND
                                                                                           VP1.Trimestre    = VP2.Trimestre + 1

    Rispetto alla tua query ho rivisto il JOIN, portandolo a LEFT (senza però gestire le casistiche NULL, quello va fatto come secondo step), e legando l'alias VP1 a VP2 sulla base di ID_Contratto, Anno, e Trimestre1 = Trimestre2 + 1

    Inoltre ho aggiunto un Delta automaticamente calcolato tra le due colonne RisparmioComplessivo.

    Fammi sapere se può andare, o se ci sono altre considerazioni da fare in merito.

    Buona giornata,


    Emiliano Musso

    giovedì 12 settembre 2013 06:42
  • Ti ringrazio per il suggerimento

    Effettivamente così ho dei risultati da filtrare ulteriormente, nello specifico seleziono le tuple attraverso distinct ed elimino quello dove VP2.ID_Contratto2 è null, ma non và

    SELECT *
    FROM (
    	SELECT DISTINCT VP1.ID_Contratto,
    		VP1.RisparmioComplessivo AS RisparmioTrimestre,
    		VP2.ID_Contratto AS ID_Contratto2, 
    		VP2.RisparmioComplessivo AS RisparmioTrimestrePrec,
    		VP1.Anno, VP1.Trimestre,
    		VP2.Anno AS AnnoTP,
    		VP2.Trimestre AS TrimestrePrec, 
    		VP2.RisparmioComplessivo - VP1.RisparmioComplessivo AS DeltaRisparmio
    	FROM vw_ViaggiRisparmioPeriodo AS VP1 LEFT OUTER JOIN
    				vw_ViaggiRisparmioPeriodo AS VP2 ON VP1.ID_Contratto = VP2.ID_Contratto AND
    				((VP1.Trimestre<4 AND VP1.Trimestre+1=VP2.Trimestre AND VP1.Anno=VP2.Anno) OR
    				(VP1.Trimestre=4 AND VP2.TRIMESTRE=1 AND VP1.Anno+1 = VP2.Anno))
    ) AS T1
    WHERE ID_Contratto2 IS NOT NULL

    Grazie ancora per la dritta

    giovedì 12 settembre 2013 09:28
  • Ho provato ad eseguire la tua query, e inserendo dati di prova ottengo dei record.

    Vorrei capire meglio in che senso non va, ovvero quale tipo di dati o di risultato ti aspetteresti, così possiamo ragionare su come affinare lo script.


    Emiliano Musso

    giovedì 12 settembre 2013 09:34
  • La vista recupera i dati attraverso diverse tabelle effettuando calcoli e restituendo in totale 210 record; in uscita dalla query sopra, mi aspetto quindi di ritrovare lo stesso numero di record. Eliminata la where la query funziona, non so se sono riuscito a spiegami

    giovedì 12 settembre 2013 09:51
  • forse ho incasinato il tutto, mi spiego: con la clausola where la query dopo circa 6 min è ancora in esecuzione, eliminandola restituisce dei risultati ma non sono quelli che mi aspetto

    giovedì 12 settembre 2013 10:10
  • salve,

    non capisco perche' filtri per vp2.ID_Contratto IS NOT NULL in quanto cosi' ti esclude la prima riga assoluta restituita...

    se ho compreso il problema, io probabilmente scriverei

    SET NOCOUNT ON;
    USE tempdb;
    GO
    CREATE TABLE dbo.vw_ViaggiRisparmioPeriodo (
    	ID_Contratto int,
    	RisparmioComplessivo int,
    	Anno int,
    	Trimestre int
    	);
    GO
    INSERT INTO dbo.vw_ViaggiRisparmioPeriodo
    	VALUES ( 1, 1, 2010, 1 ), ( 1, 2, 2010, 2 ), ( 1, 3, 2010, 3 ), ( 1, 4, 2010, 4 ),
    		( 1, 5, 2011, 1 ), ( 1, 6, 2011, 2 ), ( 1, 7, 2011, 3 ), ( 1, 5, 2011, 4 );
    GO
    SELECT vp1.ID_Contratto, vp1.RisparmioComplessivo AS RisparmioTrimestre, vp1.Anno, vp1.Trimestre
    	, vp2.ID_Contratto AS ID_ContrattoPrec, vp2.RisparmioComplessivo AS RisparmioTrimestrePrec, vp2.Anno AS AnnoPrec, vp2.Trimestre AS TrimestrePrec
    	, vp1.RisparmioComplessivo - vp2.RisparmioComplessivo AS Delta
    	FROM dbo.vw_ViaggiRisparmioPeriodo vp1
    		LEFT JOIN dbo.vw_ViaggiRisparmioPeriodo vp2 ON vp1.ID_Contratto = vp2.ID_Contratto 
    			AND	(vp2.Anno = CASE WHEN vp1.Trimestre = 1 THEN vp1.Anno -1 ELSE vp1.Anno END)
    			AND (vp2.Trimestre = CASE WHEN vp1.Trimestre = 1 THEN 4 ELSE vp1.Trimestre -1 END)
    	ORDER BY vp1.ID_Contratto, vp1.Anno, vp1.Trimestre;
    GO
    DROP TABLE dbo.vw_ViaggiRisparmioPeriodo;
    

    eventualmente con 

    , vp1.RisparmioComplessivo - ISNULL(vp2.RisparmioComplessivo, 0) AS Delta

    volendo eliminare il NULL del Delta finale, anche se questo avrebbe fisiologicamente anche senso..

    saluti


    http://www.hotelsole.com/asql/index.php - DbaMgr2k - DbaMgr and further SQL Tools http://www.hotelsole.com/

    giovedì 12 settembre 2013 10:44
    Moderatore
  • a me interessa eliminare i record con valori nulli risultanti dalla join ed avere di conseguenza i miei 210 record; nel moneto in cui ID_Contratto2 è null l'intera riga non è utile. Inizio a pensare che il problema sia nei miei dati...

    cerco di estrarre dei dati dal mio db e di postarveli in modo che possa spiegarmi meglio

    In ogni modo grazie di nuovo

    giovedì 12 settembre 2013 11:22
  • Forse sono giunto alla conclusione: il problema era nella struttura della vista, ho modificato la stessa in modo da essere più vicina alla soluzione finale, in questo modo comprendere altri campi su cui effettuare il confronto (SiglaTratta, ID_TipoViaggio) e adesso si presenta così: 

    [vw_ViaggiRisparmioPeriodo]:
    	[ID_Contratto]
    	,[RagioneSociale]
    	,[DataViaggio]
    	,[Mese]
    	,[SiglaTratta]
    	,[CostoMedioValRifEsclComm]
    	,[CommissioniValRif]
    	,[IndiceIstatValRif]
    	,[CostoIVAEsclusa]
    	,[Commissioni]
    	,[CostoTotale]
    	,[ID_TipoViaggio]
    	,[Indice]
    	,[IndiceIstatPercentAbb]
    	,[CostoStdEsclComm]
    	,[CostoStdInclComm]
    	,[RisparmioTrattaPresente]
    	,[RisparmioTrattaPresentePercent]
    	,[RisparmioTrattaNonPresente]
    	,[RisparmioComplessivo]
    	,[Anno]
    	,[Trimestre]
    
    

    metre la query modificata secondo i vostri suggerimenti è la seguente:

    SELECT	VP1.ID_Contratto, VP1.RagioneSociale,
    		VP1.DataViaggio, VP1.Mese,
    		VP1.SiglaTratta, VP1.CostoMedioValRifEsclComm,
    		VP1.CommissioniValRif, VP1.IndiceIstatValRif, 
    		VP1.CostoIVAEsclusa, VP1.Commissioni, 
    		VP1.CostoTotale, VP1.ID_TipoViaggio,
    		VP1.Indice, VP1.IndiceIstatPercentAbb,
    		VP1.CostoStdEsclComm,
    		VP1.CostoStdInclComm,
    		VP1.RisparmioTrattaPresente, 
    		VP1.RisparmioTrattaPresentePercent,
    		VP1.RisparmioTrattaNonPresente,
    		VP1.RisparmioComplessivo, 
    		VP1.Anno, VP1.Trimestre,
    		VP2.RisparmioComplessivo AS RisparmioConsuntivato,
    		VP1.RisparmioComplessivo-VP2.RisparmioComplessivo AS RisparmioDaConsuntivare
    FROM	vw_ViaggiRisparmioPeriodo AS VP1 LEFT OUTER JOIN
    		vw_ViaggiRisparmioPeriodo AS VP2 ON 
    		VP1.ID_TipoViaggio = VP2.ID_TipoViaggio AND
    		VP1.ID_Contratto = VP2.ID_Contratto AND
    		VP1.SiglaTratta = VP2.SiglaTratta AND
    		((VP1.Trimestre<4 AND VP1.Trimestre=VP2.Trimestre+1 AND
    		VP1.Anno=VP2.Anno) OR
    		(VP1.Trimestre=4 AND VP2.Trimestre=1 AND
    		VP1.Anno=VP2.Anno+1))

    Spero di arrivare entro la serata ad un conclusione definitava.

    Buon pomeriggio

    Stefano

     
    giovedì 12 settembre 2013 14:25