Cuando se trabaja con la limpieza de datos en SQL Server, es común encontrarse con situaciones en las que es necesario comparar filas y realizar operaciones basadas en ciertas condiciones. Un enfoque para evitar el uso de cursores es utilizando el campo IDENTITY() y self-joins. Sin embargo, este método puede volverse problemático cuando los números de IDENTITY() no son secuenciales debido a filas faltantes.
Afortunadamente, hay un truco que puede ayudar a superar este problema. El truco consiste en utilizar una Expresión de Tabla Común (CTE) y la función de ventana ROW_NUMBER() como parte de una instrucción UPDATE. Esta técnica se puede utilizar en SQL Server 2005 o superior.
Echemos un vistazo a un ejemplo para demostrar este truco:
-- Configurar una variable de tabla con algunos datos que tienen duplicados y algunos duplicados inciertos
DECLARE @SomeData TABLE (
RowID INT UNIQUE,
EmpID VARCHAR(8),
PositionTitle VARCHAR(40),
PositionEffDate DATETIME,
PositionID VARCHAR(8)
);
-- Insertar datos de muestra en la variable de tabla
INSERT INTO @SomeData VALUES
(1, '00000012', 'Gerente', '1/1/2000', 'ABC123'),
(2, '00000012', 'Gerente', '1/1/2000', 'ABC123ZZ'),
(3, '00000012', 'Sr. Gerente', '1/1/2002', 'ABC125'),
(4, '00000012', 'Sr. Gerente', '1/1/2002', 'ABC125'),
(5, '00000012', 'Sr. Gerente', '1/1/2002', 'ABC125ZZ'),
(6, '00000012', 'Director', '1/1/2006', 'ABC126'),
(7, '00000012', 'Director', '1/1/2006', 'ABC126'),
(8, '00000012', 'Sr. Director', '1/1/2009', 'ABC129ZZ');
-- Eliminar filas que son duplicados ciertos
DELETE FROM @SomeData
WHERE RowID IN (
SELECT compare.RowID
FROM @SomeData main
LEFT OUTER JOIN @SomeData compare ON main.EmpID = compare.EmpID
AND main.RowID = compare.RowID - 1
WHERE main.PositionTitle = compare.PositionTitle
AND main.PositionID = compare.PositionID
AND main.PositionEffDate = compare.PositionEffDate
);
-- Renumerar los RowIDs utilizando una CTE y la función ROW_NUMBER()
WITH newPH AS (
SELECT RowID, ROW_NUMBER() OVER (ORDER BY RowID ASC) AS [newRowID]
FROM @SomeData
)
UPDATE newPH SET RowID = newRowID;
-- Eliminar las filas duplicadas restantes, manteniendo la primera fila que coincide
DELETE FROM @SomeData
WHERE RowID IN (
SELECT compare.RowID
FROM @SomeData main
LEFT OUTER JOIN @SomeData compare ON main.EmpID = compare.EmpID
AND main.RowID = compare.RowID - 1
WHERE main.PositionTitle = compare.PositionTitle
AND main.PositionEffDate = compare.PositionEffDate
);
-- Ver el resultado final
SELECT 'Arreglado' AS [Descripción], * FROM @SomeData;
En este ejemplo, comenzamos configurando una variable de tabla con algunos datos que contienen duplicados y duplicados inciertos. Luego eliminamos las filas que son duplicados ciertos basados en el título del puesto, la fecha efectiva y el ID del puesto.
A continuación, utilizamos una CTE y la función ROW_NUMBER() para renumerar los RowIDs en orden secuencial. Esto asegura que los números de IDENTITY() sean consistentes y se puedan utilizar para operaciones adicionales.
Finalmente, eliminamos las filas duplicadas restantes, manteniendo solo la primera fila que coincide basada en el título del puesto y la fecha efectiva. El resultado es un conjunto de datos limpio y arreglado.
Al utilizar este truco, puede gestionar eficientemente las tareas de limpieza de datos en SQL Server sin recurrir a cursores. Proporciona un enfoque más simplificado y optimizado para manejar comparaciones y eliminaciones.
Recuerde utilizar punto y coma después de sus declaraciones al trabajar con CTEs o declaraciones MERGE para evitar cualquier ambigüedad en el código.
¡Pruebe esta técnica en su próximo proyecto de limpieza de datos y vea cómo simplifica su flujo de trabajo!