SQL confronto 3 colonne

di il
1 risposte

SQL confronto 3 colonne

Ciao ragazzi,

per ogni CodDb ho multiple DataDecorrenza e StatoDb.

per ogni CodDb la DataDecorrenza piu recente deve avere lo StatoDb = 0. Tutti altri StatoDb con le DataDecorrenza inferiore alla data piu recente deve essere 1. Pratticamente, Ogni codice deve avere solo un StatoDb=0 che deve corrispondere all'ultima DataDecorrenza.

Come posso fare questo controllo in SQL?

1 Risposte

  • Re: SQL confronto 3 colonne

    Salve,

    parli di “controllo”, quindi ritengo tu voglia ad esempio una proiezione che ritorni come risultato “le righe” non valide…

    con la seguente popolazione

    INSERT INTO dbo.t
    VALUES ( '0015177', '2014-11-07', 1 ), ( '0015177', '2016-08-30', 1 ), ( '0015177', '2021-05-26', 0 ) -- OK
     , ( '0015177M', '2015-09-08', 0 ), ( '0015177M', '2021-05-26', 0 )  -- FAIL
     , ( '0000034011', '2018-07-11', 1 ), ( '0000034011', '2018-07-27', 0 ) -- OK
     ;

    avremmo come FAIL la “prima riga” (temporale DESC) della partition ‘0015177M’

    parlo di “partition” perche' probabilmente io ragionerei, appunto, per data islands, o partizioni… per ogni partizione ordinderei in base alla colonna temporale DESC assegnandogli un ROW_NUMBER, in modo da sapere che, appunto, ROW_NUMBER == 1 corrisponde all'ultima riga della partizione, e quindi possiamo verificare che StatoDB sia 1/0 in base al valore appunto di ROW_NUMBER

    trivialmente:

    WITH ctePartition AS (
    SELECT t.CodDB, t.DataDecorrenza, t.StatoDb, ROW_NUMBER() OVER (PARTITION BY t.CodDB ORDER BY t.DataDecorrenza DESC) AS rn
     FROM dbo.t t
    )
    WITH ctePartition AS (
    	SELECT t.CodDB, t.DataDecorrenza, t.StatoDb, ROW_NUMBER() OVER (PARTITION BY t.CodDB ORDER BY t.DataDecorrenza DESC) AS rn
    		FROM dbo.t t
    	)
    	SELECT t.CodDB, t.DataDecorrenza, t.StatoDb
    		, t.rn
    		, CASE WHEN t.rn = 1 AND t.StatoDb = 0 
    			OR t.rn >= 0 AND t.StatoDb = 1
    				THEN 'OK'
    			ELSE 'FAIL' END AS [checkStatus] 
    		
    		FROM ctePartition t
    
    		ORDER BY t.CodDB, t.DataDecorrenza DESC;
    
    — < --------
    CodDB      DataDecorrenza          StatoDb rn                   checkStatus
    ---------- ----------------------- ------- -------------------- -----------
    0000034011 2018-07-27 00:00:00.000 0       1                    OK
    0000034011 2018-07-11 00:00:00.000 1       2                    OK
    0015177    2021-05-26 00:00:00.000 0       1                    OK
    0015177    2016-08-30 00:00:00.000 1       2                    OK
    0015177    2014-11-07 00:00:00.000 1       3                    OK
    0015177M   2021-05-26 00:00:00.000 0       1                    OK
    0015177M   2015-09-08 00:00:00.000 0       2                    FAIL

     quindi, possiamo anche ovviamente filtrare relativamente all'espressione per proiettare le “righe errate”:

    WITH ctePartition AS (
    	SELECT t.CodDB, t.DataDecorrenza, t.StatoDb, ROW_NUMBER() OVER (PARTITION BY t.CodDB ORDER BY t.DataDecorrenza DESC) AS rn
    		FROM dbo.t t
    	)
    	SELECT t.CodDB, t.DataDecorrenza, t.StatoDb
    		, t.rn
    		, CASE WHEN t.rn = 1 AND t.StatoDb = 0 
    			OR t.rn >= 0 AND t.StatoDb = 1
    				THEN 'OK'
    			ELSE 'FAIL' END AS [checkStatus] 
    				
    			FROM ctePartition t
    		
    		WHERE 1 = 
    			CASE WHEN t.rn = 1 AND t.StatoDb = 0 
    					OR t.rn >= 0 AND t.StatoDb = 1
    						THEN 0
    					ELSE 1 END 
    		ORDER BY t.CodDB, t.DataDecorrenza DESC;
    
    –< -----
    CodDB      DataDecorrenza          StatoDb rn                   checkStatus
    ---------- ----------------------- ------- -------------------- -----------
    0015177M   2015-09-08 00:00:00.000 0       2                    FAIL

    ma forse non ho ben compreso quanto chiedi…

    salutoni romagnoli
    – 
    Andrea

Devi accedere o registrarti per scrivere nel forum
1 risposte