QUALITÉ DES DONNÉES : recherche d’intervals anormaux

Voici une petite requête dynamique pour rechercher dans toutes les tables des intervalles anormaux, c’est à dire dont les bornes sont inversées. Par exemple lorsqu’une date de début est postérieur à une date de fin…
Cela arrive plus fréquemment qu’on ne le croit, et surtout dans les bases de données dans lesquelles on n’a pas mis de contraintes CHECK (comme c’est le case par exemple pour MySQL ou la contrainte CHECK n’existe pas !)

NOTA : bien que le code soit donné pour MS SQL Server, il est facile à transposer dans n’importe quel autre SGBDR.


DECLARE @SQL VARCHAR(max);
SET @SQL = '';
 
WITH  
T0 AS
(SELECT 'begin' AS C1, 'end' AS C2
 UNION ALL
 SELECT 'start' AS C1, 'end' AS C2
 UNION ALL
 SELECT 'start' AS C1, 'stop' AS C2
 UNION ALL
 SELECT 'first' AS C1, 'last' AS C2
 UNION ALL
 SELECT 'before' AS C1, 'after' AS C2
 UNION ALL
 SELECT 'lead' AS C1, 'lag' AS C2
 UNION ALL
 SELECT 'inf' AS C1, 'sup' AS C2
 UNION ALL
 SELECT 'min' AS C1, 'max' AS C2
 UNION ALL
 SELECT 'precedent' AS C1, 'suivant' AS C2
 UNION ALL
 SELECT 'premier' AS C1, 'dernier' AS C2
 UNION ALL
 SELECT 'devant' AS C1, 'derriere' AS C2
 UNION ALL
 SELECT 'avant' AS C1, 'apres' AS C2
 UNION ALL
 SELECT 'commence' AS C1, 'fini' AS C2
),  
T1 AS  
(  
SELECT T1.TABLE_SCHEMA, T1.TABLE_NAME,  
       T1.COLUMN_NAME AS COL_DEBUT,  
       T2.COLUMN_NAME AS COL_FIN  
FROM   INFORMATION_SCHEMA.COLUMNS AS T1  
       INNER JOIN INFORMATION_SCHEMA.COLUMNS AS T2  
             ON T1.TABLE_SCHEMA = T2.TABLE_SCHEMA  
                AND T1.TABLE_NAME = T2.TABLE_NAME  
                AND T1.COLUMN_NAME <> T2.COLUMN_NAME  
),
T2 AS
(SELECT *  
 FROM   T1
        CROSS JOIN T0  
 WHERE  COL_DEBUT COLLATE French_CI_AI LIKE '%' + C1 + '%'  
   AND  COL_FIN   COLLATE French_CI_AI LIKE '%' + C2 + '%'
   AND  REPLACE(COL_DEBUT COLLATE French_CI_AI, C1, '') =  
        REPLACE(COL_FIN   COLLATE French_CI_AI, C2, '')
)    
 
SELECT @SQL = @SQL + 'SELECT ''' + TABLE_SCHEMA + '.' + TABLE_NAME  
                   + ' :: ' + COL_DEBUT +' / ' + COL_FIN  
                   +''' AS DATA, COUNT(*) AS NB FROM [' + TABLE_SCHEMA + '].[' + TABLE_NAME  
                   +'] WHERE [' +  COL_DEBUT +'] > [' + COL_FIN +'] UNION ALL '  
FROM   T2
 
SET @SQL = 'WITH T AS (' + SUBSTRING(@SQL, 1, LEN(@SQL) - 10) +') SELECT * FROM T WHERE NB > 0;'
 
EXEC (@SQL)

Bien entendu dans la première CTE vous pouvez rajouter autant de couples de noms présentant les mêmes caractéristiques afi d’augmenter les chances de débusquer les données fausses.


--------
Frédéric Brouard, SQLpro - ARCHITECTE DE DONNÉES, http://sqlpro.developpez.com/
Expert bases de données relationnelles et langage SQL. MVP Microsoft SQL Server
www.sqlspot.com : modélisation, conseil, audit, optimisation, tuning, formation
* * * * *  Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence  * * * * *

MVP Microsoft SQL Server

Laisser un commentaire