No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Curso Práctico de SQL

Curso Práctico de SQL

Israel Vázquez Morales

Israel Vázquez Morales

Duplicados

15/29
Recursos

Query de inserción

insert into platzi.alumnos (id, nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id) values (1001, 'Pamelina', null, '[email protected]', 4800, '2020-04-26 10:18:51', 12, 16)

Aportes 267

Preguntas 17

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Query Ejercicio:

insert into platzi.alumnos (id, nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id) values (1000, 'Pamelina', null, '[email protected]', 4800, '2020-04-26 10:18:51', 12, 16);

La cláusula HAVING es una implemetacion que el sistema gestor de bases de datos SQL crea para complementar el condicionante WHERE, ya que el condicionante WHERE no permite utilizar funciones de agregación como SUM, MAX, MIN o AVG, es decir, con un condicionante WHERE no podemos crear consultas válidas que sean capaz de devolvernos los datos de los clientes que compraron más de 1000 productos durante un año, por ejemplo.

Tener esto en cuenta por si tampoco entendieron nada y este es su primer curso de base de datos 😉

En el ejercicio de encontrar un DUPLICADO, se está haciendo una partición de la tabla de todos los valores en filas de cada una de las variables o columnas de la tabla a excepción del id, el cual no puede ser igual y no se repite al ser una primary key.

Cuando se aplica esta partición en cada valor se hace único los valores, es decir, cada row viene siendo una partición, y al utilizar la función agregada que en este caso es ROW_NUMBER() va a contar los valores de cada una de las particiones haciendo que se reinicie los “números de fila” cuando salta de partición en partición. por eso, cuando encuentra dos valores iguales, enumera los dos valores, dejando como valor en su row un 2.

Por si necesitan el código para insertar una fila

insert into platzi.alumnos (id, nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id) values (1001, 'Pamelina', null, '[email protected]', 4800, '2020-04-26 10:18:51', 12, 16);

Por lógica no puede existir 2 correos iguales, por lo tanto realice la actividad en base a eso

  • Primero certifique que existían correos duplicados.
SELECT email,COUNT(*)
FROM platzi.alumnos
GROUP BY email
HAVING COUNT(*) > 1;

De esa forma obtuve el nombre del correo repetido, en base a ello, se que puedo realizar la agrupación por partición utilizando unicamente el correo.

  • Ahora valido que obtengo el id del correo duplicado.
SELECT id 
FROM (
	SELECT id, ROW_NUMBER() OVER(PARTITION BY email ORDER BY id) AS row
	FROM platzi.alumnos
) AS duplicados
WHERE duplicados.row > 1;

Una vez certificado que obtengo el id del dato duplicado, procedo a borrar el registro.

DELETE FROM platzi.alumnos
where id = (
SELECT id 
FROM (
	SELECT id, ROW_NUMBER() OVER(PARTITION BY email ORDER BY id) AS row
	FROM platzi.alumnos
) AS duplicados
WHERE duplicados.row > 1
);

¡Ánimo vas por la mitad!

Solucion al reto

DELETE
    FROM platzi.alumnos
    WHERE id IN (SELECT id FROM (
        SELECT *
            FROM (SELECT id, ROW_NUMBER() OVER(
            PARTITION BY 
                nombre, apellido, 
                email, colegiatura,
                fecha_incorporacion, carrera_id,
                tutor_id
            ORDER BY id ASC) AS row
            FROM platzi.alumnos
    ) AS duplicados
    WHERE duplicados.row > 1) AS duplicados_id);

Para SQL Server:

-- METODO 1
-- MOSTRAR DUPLICADO A PARTIR DEL ID
USE [platzi]
SELECT *
FROM platzi.alumnos AS ou
WHERE 
(
	SELECT COUNT(*)
	FROM platzi.alumnos AS inr
	WHERE ou.id = inr.id
) > 1
GO


-- METODO 2
-- MOSTRAR DUPLICADO COMPARANDO TODOS LOS CAMPOS, EXCEPTO EL ID
USE [platzi]
SELECT CONCAT(platzi.alumnos.nombre,',',
			  platzi.alumnos.apellido,',',
			  platzi.alumnos.email,',',
			  platzi.alumnos.colegiatura,',',
			  platzi.alumnos.fecha_incorporacion,',',
			  platzi.alumnos.carrera_id,',',
			  platzi.alumnos.tutor_id), COUNT(*)
FROM platzi.alumnos
GROUP BY CONCAT(platzi.alumnos.nombre,',',
			  platzi.alumnos.apellido,',',
			  platzi.alumnos.email,',',
			  platzi.alumnos.colegiatura,',',
			  platzi.alumnos.fecha_incorporacion,',',
			  platzi.alumnos.carrera_id,',',
			  platzi.alumnos.tutor_id)
HAVING COUNT(*) >1
ORDER BY COUNT(*) DESC
GO


-- METODO 3
-- MOSTRAR DUPLICADO COMPARANDO TODOS LOS CAMPOS, EXCEPTO EL ID CON SUBCONSULTA
USE [platzi]
SELECT *
FROM 
(
	SELECT ROW_NUMBER() OVER(PARTITION BY nombre,apellido,email,colegiatura,
									   fecha_incorporacion,carrera_id,tutor_id 
						  ORDER BY id ASC) AS row, *
	FROM platzi.alumnos
) AS duplicados
WHERE duplicados.row > 1
ORDER BY row DESC

Soy bastante nuevo en este mundo así que tuve que hacer una especie de corrida en frío para entenderlo y poder crear una imagen en mi cabeza de lo que sucede en las subconsultas. Dejo esto que es lo que veo en mi mente sobre el código de la case por si a alguien le sirve. Me corrigen los expertos por fa c:

Para los que usan MySQL Workbench, pueden encontrar los duplicados usando CONCAT_WS de la siguiente forma :

Por si quieren entender mejor como funciona el PARTITION BY, me sirvió mucho para comprender:

15. Duplicados

SELECT *
FROM platzi.alumnos AS ou
WHERE (
	SELECT COUNT(*)
	FROM platzi.alumnos AS inr
	WHERE ou.id = inr.id
) > 1;

SELECT (platzi.alumnos.*)::text, COUNT(*)
FROM platzi.alumnos 
GROUP BY platzi.alumnos.*
HAVING COUNT(*) > 1;

SELECT (
	   platzi.alumnos.nombre,
	   platzi.alumnos.apellido,
	   platzi.alumnos.email,
	   platzi.alumnos.colegiatura,
	   platzi.alumnos.fecha_incorporacion,
 	   platzi.alumnos.carrera_id,
	   platzi.alumnos.tutor_id
	   )::text, COUNT(*)
FROM platzi.alumnos 
GROUP BY  platzi.alumnos.nombre,
	   platzi.alumnos.apellido,
	   platzi.alumnos.email,
	   platzi.alumnos.colegiatura,
	   platzi.alumnos.fecha_incorporacion,
 	   platzi.alumnos.carrera_id,
	   platzi.alumnos.tutor_id
HAVING COUNT(*) > 1;

SELECT *
FROM (
	SELECT id,
	ROW_NUMBER() OVER(
		PARTITION BY
			nombre,
			apellido,
	email,
	colegiatura,
	fecha_incorporacion,
	carrera_id,
	tutor_id
	ORDER BY id ASC
	)AS row,
	*
	FROM platzi.alumnos
)AS duplicados
WHERE duplicados.row > 1;

mismo resultado mucho mas fácil:

select nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id, count(nombre)
from platzi.alumnos
group by nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id
having count()>1

Para encontrar duplicados basados en sus datos principales: nombre, apellido y email.

select (nombre,apellido,email)::text as datos_usuarios, count(*) as cantidad 
from platzi.alumnos
group by (nombre,apellido,email)
order by cantidad desc```

Ejercicio cumplido…

DELETE FROM platzi.alumnos
WHERE id IN (
SELECT id
FROM (
	SELECT id,
	ROW_NUMBER() over(
		PARTITION BY
			nombre,
			apellido,
			email,
			colegiatura,
			fecha_incorporacion,
			carrera_id,
			tutor_id
		ORDER BY id ASC
	)AS row
	
	FROM platzi.alumnos
)AS duplicados
WHERE duplicados.row > 1);```

Para entender de manera mas simple lo que esta pasando en el ultimo query, les recomendo que corran esta query:

SELECT *, ROW_NUMBER() OVER(PARTITION BY colegiatura) AS row
FROM platzi.alumnos;

Asi se dan cuenta como funciona a menor escala para luego interpretar lo demas, espero ser de ayuda!

No me sirvieron los ejemplos en workbench 😦

Solución al reto anterior

SELECT * 
    FROM (
        SELECT *, 
			DATE_PART('YEAR', fecha_incorporacion) AS anio_incorporacion,
			DATE_PART('MONTH', fecha_incorporacion) AS mes_incorporacion
        FROM platzi.alumnos
    ) AS alumnos_con_anio
    WHERE anio_incorporacion = 2018 AND mes_incorporacion = 5;```

La solucion en MySQL WorkBench seria:

<SELECT *
FROM (
	SELECT *, YEAR(fecha_incorporacion) AS Ano, MONTH(fecha_incorporacion) AS Mes
    FROM platzi.alumnos
    ) AS Fechas
WHERE Ano=2018 AND Mes=5;>

Mi solución al reto (postgreSQL):

DELETE FROM platzi.alumnos
WHERE id IN(
SELECT table_alumnos.id
FROM (
	SELECT
		ROW_NUMBER() OVER(
			PARTITION BY
			a1.nombre,
			a1.apellido,
			a1.email,
			a1.colegiatura,
			a1.fecha_incorporacion,
			a1.carrera_id,
			a1.tutor_id
			ORDER BY a1.id ASC
		) AS row_alumnos, a1.*
	FROM platzi.alumnos as a1
) AS table_alumnos
WHERE table_alumnos.row_alumnos>1
)
Esta es una versión menos compleja para ver los duplicados: ```txt SELECT * FROM ( SELECT *, COUNT(*) OVER(PARTITION BY email) AS copias FROM platzi.alumnos) AS loquesea WHERE copias > 1; ``` Con la ventaja adicional de poder ver cada registro pos separado. Para borrar, el código si es casi el mismo que el del profesor. ```txt DELETE FROM platzi.alumnos WHERE id IN ( SELECT id FROM ( SELECT id, ROW_NUMBER() OVER (PARTITION BY email) AS copias FROM platzi.alumnos ) AS busqueda WHERE busqueda.copias > 1 ); ```DELETE FROM platzi.alumnos WHERE id IN ( SELECT id FROM ( SELECT id, ROW\_NUMBER() OVER (PARTITION BY email) AS copias FROM platzi.alumnos ) AS busqueda WHERE busqueda.copias > 1 );

¡Hola! aquí dejo una alternativa al reto de la clase anterior mucho más sencilla y con menos líneas de código, en el caso de que no nos interese crear nuevas columnas para el año y el mes.
Esta solución se enfoca en obtener la respuesta a la pregunta sin modificar la tabla en el proceso de consulta:

SELECT *
FROM platzi.alumnos
WHERE (EXTRACT(YEAR FROM fecha_incorporacion)) = 2019
AND
(EXTRACT(MONTH FROM fecha_incorporacion)) = 5;

Para la parte de la function window row\_number() over(partition by ...) creo que se debió haber explicado un poco mejor. Acá encontré la razón del por qué la proyección SQL que hizo el profe funciona <https://www.postgresqltutorial.com/postgresql-window-function/postgresql-row_number/>

soluciòn para eliminar el campo duplicado

DELETE
FROM platzi.alumnos
WHERE id IN (
SELECT id
FROM (
SELECT id,
ROW_NUMBER () OVER (
PARTITION BY
nombre,
apellido,
email,
colegiatura,
fecha_incorporacion,
carrera_id,
tutor_id
ORDER BY id ASC
) AS row
FROM platzi.alumnos
) AS duplicados
WHERE duplicados.row >1);

-- Tarea -> Eliminar los duplicados de la tabla platzi.alumnos
DELETE
FROM platzi.alumnos
WHERE id IN (SELECT id
FROM (
	SELECT --id,
	ROW_NUMBER() OVER(
		PARTITION BY
			nombre,
			apellido,
			email,
			colegiatura,
			fecha_incorporacion,
			carrera_id,
			tutor_id
		ORDER BY id ASC
		) AS ROW, *
		FROM platzi.alumnos
) AS duplicados
WHERE duplicados.row > 1);

Lo que paso en el último query fue que en vez de contar los rows, como lo solíamos hacer, ahora los estamos separando de acuerdo a ciertas características especificadas en la Partición. Eso significa que ahora cada row con un name, email, lastname, career_id, tutor_id, etc. único van a tener un valor de 1 en la columna row. Cada vez que haya otra tupla igual, ese valor va a aumentar en uno

Para la tarea ocupé los dos métodos mezclados, tal vez en la práctica nada recomendado pero para fines de practicar me pareció útil.

SELECT *
FROM platzi.alumnos

WHERE(EXTRACT(MONTH FROM fecha_incorporacion)) = 05
and
(DATE_PART('YEAR', fecha_incorporacion)) = 2018
;```

Solucion:

DELETE
    FROM platzi.alumnos
    WHERE id IN (SELECT id FROM (
        SELECT *
            FROM (SELECT id, ROW_NUMBER() OVER(
            PARTITION BY 
                nombre, apellido, 
                email, colegiatura,
                fecha_incorporacion, 
		carrera_id,
                tutor_id
            ORDER BY id ASC) AS row
            FROM platzi.alumnos
    ) AS duplicados
    WHERE duplicados.row > 1) AS duplicados_id);
Mi solución al reto usando una CTE ```js WITH duplicados AS ( SELECT id, ROW_NUMBER() OVER ( PARTITION BY nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id ORDER BY id ASC ) AS row FROM platzi.alumnos ) DELETE FROM platzi.alumnos WHERE id IN ( SELECT id FROM duplicados WHERE row > 1 ); ```WITH duplicados AS ( SELECT id, ROW\_NUMBER() OVER ( PARTITION BY nombre, apellido, email, colegiatura, fecha\_incorporacion, carrera\_id, tutor\_id ORDER BY id ASC ) AS row FROM platzi.alumnos ) DELETE FROM platzi.alumnos WHERE id IN ( SELECT id FROM duplicados WHERE row > 1 );
Reto anterior SELECT \* FROM alumnos WHERE EXTRACT(YEAR FROM fecha\_incorporacion)=2019 AND EXTRACT(MONTH FROM fecha\_incorporacion)=05;
![](https://static.platzi.com/media/user_upload/image-2762c890-19c9-411d-a63e-64f0bf06d6ad.jpg)
![](https://static.platzi.com/media/user_upload/image-91c79244-43a2-4589-9e93-8b8c227f4c9a.jpg)
Qué es mejor para el filtrado en cuestión de optimización o buenas prácticas; el subquery dentro del FROM donde usas el EXTRACT o DATE\_PART o usar el filtrado en el WHERE?
Borrado de duplicados: ```js -- Eliminar duplicados manteniendo la primera ocurrencia (ID más bajo) WITH duplicates AS ( SELECT id FROM ( SELECT id, ROW_NUMBER() OVER ( PARTITION BY nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id ORDER BY id ASC ) AS row_num FROM platzi.alumnos ) AS subquery WHERE row_num > 1 ) DELETE FROM platzi.alumnos WHERE id IN (SELECT id FROM duplicates); ```-- Eliminar duplicados manteniendo la primera ocurrencia (ID más bajo) WITH duplicates AS ( SELECT id FROM ( SELECT id, ROW\_NUMBER() OVER ( PARTITION BY nombre, apellido, email, colegiatura, fecha\_incorporacion, carrera\_id, tutor\_id ORDER BY id ASC ) AS row\_num FROM platzi.alumnos ) AS subquery WHERE row\_num > 1 ) DELETE FROM platzi.alumnos WHERE id IN (SELECT id FROM duplicates);
`SELECT *` `FROM platzi.alumnos` `WHERE EXTRACT(YEAR FROM fecha_incorporacion) = 2018` `AND EXTRACT(MONTH FROM fecha_incorporacion) = 5;` `SELECT * FROM platzi.alumnos` `WHERE fecha_incorporacion >= '2018-05-01' ` `AND fecha_incorporacion < '2018-06-01';`
```txt WITH duplicados AS ( SELECT id, ROW_NUMBER() OVER( PARTITION BY nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id ORDER BY id ASC ) AS row FROM platzi.alumnos ) DELETE FROM platzi.alumnos WHERE id IN ( SELECT id FROM duplicados WHERE row > 1 ); ```
Para trabajar con duplicados en una tabla en PostgreSQL, puedes identificarlos, eliminarlos o gestionarlos según lo que necesites. Aquí tienes algunas opciones comunes: ### **1. Identificar duplicados** Si quieres encontrar filas duplicadas basadas en una o varias columnas: SELECT columna1, columna2, COUNT(\*) FROM nombre\_tabla GROUP BY columna1, columna2 HAVING COUNT(\*) > 1; Esto muestra las combinaciones de `columna1` y `columna2` que tienen duplicados. ### **2. Eliminar duplicados** #### a. **Mantener sólo una fila por duplicado** Puedes usar una subconsulta con `ROW_NUMBER()` para eliminar duplicados, conservando una sola fila por grupo: DELETE FROM nombre\_tabla WHERE id NOT IN ( SELECT MIN(id) FROM nombre\_tabla GROUP BY columna1, columna2 ); Aquí, `columna1` y `columna2` son las columnas que identifican los duplicados. #### b. **Usando** `CTE` **y** `ROW_NUMBER` Otra forma común es usar una expresión común de tabla (CTE): WITH cte AS ( SELECT id, ROW\_NUMBER() OVER (PARTITION BY columna1, columna2 ORDER BY id) AS fila FROM nombre\_tabla ) DELETE FROM nombre\_tabla WHERE id IN ( SELECT id FROM cte WHERE fila > 1 ); Esto elimina todas las filas duplicadas excepto la primera. ### **3. Insertar datos evitando duplicados** Si deseas insertar filas en una tabla pero evitar duplicados, puedes usar la cláusula `ON CONFLICT`: INSERT INTO nombre\_tabla (columna1, columna2) VALUES ('valor1', 'valor2') ON CONFLICT (columna1, columna2) DO NOTHING; Esto asegura que no se insertarán filas duplicadas basadas en las columnas indicadas. ### **4. Crear restricciones para evitar duplicados en el futuro** #### a. **Índices únicos** Agrega una restricción única a las columnas relevantes: ALTER TABLE nombre\_tabla ADD CONSTRAINT unica\_columna UNIQUE (columna1, columna2); Esto evitará que se inserten duplicados en esas columnas. ### **5. Contar duplicados** Si deseas solo saber cuántos registros duplicados hay: SELECT COUNT(\*) - COUNT(DISTINCT columna1, columna2) AS total\_duplicados FROM nombre\_tabla; Esto calcula el número de filas duplicadas en la tabla.
SELECT \* FROM ALUMNOS WHERE DATEPART(YEAR, FECHA\_INCORPORACION)=2018 AND DATEPART(MONTH, FECHA\_INCORPORACION) = 5
Me enreda un poco esta clase. Es como la broma de las indicaciones a alguien que no sabe llegar a un lugar: «Sigues derecho por esta calle y cuando llegues al poste, te devuelves porque por ahí no es. Entonces giras a la izquierda, llegando al parque volteas a la derecha y, cuando llegues a la silla, te devuelves porque por ahí no es tampoco...» Es bueno saber qué no se debe hacer... pero eso se adquiere con experiencia.
Para eliminar todos los duplicados lo realice de la siguiente manera ```js SELECT * FROM platzi.alumnos AS a INNER JOIN ( SELECT nombre, apellido, email, colegiatura, fecha_incorporacion,carrera_id,tutor_id FROM platzi.alumnos GROUP BY nombre, apellido, email, colegiatura, fecha_incorporacion,carrera_id,tutor_id HAVING COUNT(*) > 1 ) AS d ON a.nombre = d.nombre ORDER BY id OFFSET 1 ```Primeramente, busque entre todas las filas que el conteo sea mayor a uno, lo ordene por el id y me salte la primera fila que seria la original, para lo cual me mostrara todas las demas filas repetidas ```js CREATE OR REPLACE FUNCTION deleteSameRows() RETURNS TABLE ( id INT, nombre TEXT, apellido TEXT, email TEXT, colegiatura TEXT, fecha_incorporacion DATE, carrera_id INT, tutor_id INT ) AS $$ BEGIN RETURN QUERY SELECT a.id, a.nombre::TEXT, a.apellido::TEXT, a.email::TEXT, a.colegiatura::TEXT, a.fecha_incorporacion::DATE, a.carrera_id::INT, a.tutor_id::INT FROM platzi.alumnos AS a INNER JOIN ( SELECT e.nombre, e.email, COUNT(*) FROM platzi.alumnos AS e GROUP BY e.nombre, e.email HAVING COUNT(*) > 1 ) AS d ON a.nombre = d.nombre AND a.email = d.email ORDER BY a.id OFFSET 1; END; $$ LANGUAGE plpgsql; ```Seguidamente cree un procedural language para ejecutar mi codigo para despues aplicar el borrado de las filas ```js DELETE FROM platzi.alumnos WHERE id IN ( SELECT id FROM deleteSameRows() ); ```Nose si sera la mejor version, pero me tomo bastante tiempo realizarlo, en especial ese procedure porque la sintaxis no es que sea muy amigable
SELECT \* FROM platzi.alumnos WHERE EXTRACT(YEAR FROM fecha\_incorporacion) = 2018 AND EXTRACT(MONTH FROM fecha\_incorporacion) = 5;
Elimine la tabla de esta forma: ```js DELETE FROM platzi.alumnos WHERE id = ( SELECT id FROM ( SELECT ROW_NUMBER() OVER( PARTITION BY nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id ORDER BY id asc ) AS filas, * FROM platzi.alumnos ORDER BY id DESC ) AS filas_rep WHERE filas > 1 ) ```
![](https://static.platzi.com/media/user_upload/image-4ec0efda-b9ad-4b13-aac0-06635fef57d1.jpg)
Asi como en python existe: `pd.drop\_duplicates` Con estas querys podemos eliminar filas duplicadas sin importar la cantidad de columnas, cuidado que puede eliminar informacion importante por lo que un backup siempre es practicamente requerido: ```js CREATE TABLE new_table AS SELECT DISTINCT * FROM your_table; ``````js DROP TABLE your_table; ALTER TABLE new_table RENAME TO your_table; ```DROP TABLE your\_table; ALTER TABLE new\_table RENAME TO your\_table;
Chicos, quise agregar más de 1 duplicado para utilizar las consultas y verificar que todo se de de forma correcta. Tengo estas líneas de códigos donde lo que hice fue agregar 10 datos (Duplicando 3 "originales"). Luego muestro dos formas de encontrar y/o visualizar los duplicados. La primera, nos indica cuántas veces se está repitiendo cada dato y la segunda, es un poco más especifica. Después de visualizar los duplicados, los eliminamos, asegurándonos que se seleccionen por grupo de duplicados y que de dicho grupo, deje el del id menor (dejando así el dato "original" sin que se vaya a eliminar tal vez duplicados de forma arbitraria). ```js ---AGREGAR LOS DATOS (DUPLICADOS) EN LA TABLA DE ALUMNOS--- INSERT INTO platzi.alumnos (id, nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id) VALUES (1001, 'Pamelina', NULL, '[email protected]', 4800, '2020-04-26 10:18:51', 12, 16), (1002, 'Pamelina', NULL, '[email protected]', 4800, '2020-04-26 10:18:51', 12, 16), (1003, 'Pamelina', NULL, '[email protected]', 4800, '2020-04-26 10:18:51', 12, 16), (1004, 'Pamelina', NULL, '[email protected]', 4800, '2020-04-26 10:18:51', 12, 16), (1005, 'Annabela', NULL, '[email protected]', 4500, '"2018-04-17 00:13:55"', 39, 23), (1006, 'Annabela', NULL, '[email protected]', 4500, '"2018-04-17 00:13:55"', 39, 23), (1007, 'Annabela', NULL, '[email protected]', 4500, '"2018-04-17 00:13:55"', 39, 23), (1008, 'Cele', 'Carrigan', '[email protected]', 2300, '2020-08-27 04:53:43', 15, 23), (1009, 'Cele', 'Carrigan', '[email protected]', 2300, '2020-08-27 04:53:43', 15, 23), (1010, 'Cele', 'Carrigan', '[email protected]', 2300, '2020-08-27 04:53:43', 15, 23); ---FORMAS DE VISUALIZAR LOS DUPLICADOS--- --#Primera forma#-- SELECT nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id, COUNT(*) AS cantidad FROM platzi.alumnos GROUP BY nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id HAVING COUNT(*) > 1; --#Segunda forma#-- SELECT id, nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id FROM ( SELECT id, nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id, COUNT(*) OVER (PARTITION BY nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id) AS cantidad FROM platzi.alumnos ) AS subconsulta WHERE cantidad > 1; ---ELIMINAR DUPLICADOS--- DELETE FROM platzi.alumnos WHERE id NOT IN ( SELECT MIN(id) FROM platzi.alumnos GROUP BY nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id); ```
Esta fue la primera solución que se me ocurrió, ahora veremos si funciona :) `DELETE FROM platzi.alumnos al WHERE al.id = (SELECT id FROM ( SELECT id, ROW_NUMBER() OVER( PARTITION BY nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id ORDER BY id ASC) AS row * FROM platzi.alumnos) AS duplicados WHERE duplicados.row >1);`
![](https://static.platzi.com/media/user_upload/image-c3f6bbf4-dbac-44d0-a16f-81771279bc5a.jpg) # Eliminar duplicados * `ROW_NUMBER()`: Asigna un número secuencial a cada fila dentro de una partición de filas que comparten el mismo valor en las columnas `nombre`, `apellido`, y `email`. * `PARTITION BY`: Divide el conjunto de resultados en grupos según las columnas que determines (en este caso, `nombre`, `apellido`, `email`). * `fila > 1`: Filtra todas las filas que son duplicadas, ya que el valor 1 representa la primera aparición de cada conjunto de duplicados.
```js WITH alumnosDuplicados AS ( SELECT * FROM ( SELECT ROW_NUMBER() OVER( PARTITION BY nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id ORDER BY id ASC ) AS row_num , * FROM alumnos ) AS duplicados ) DELETE FROM alumnos WHERE id IN ( SELECT id FROM alumnosDuplicados WHERE row_num > 1 ) ```
Este es el Query para eliminar duplicados y conservar el original o primero: WITH cte AS ( SELECT id, ROW\_NUMBER() OVER(PARTITION BY nombre, apellido, email ORDER BY id) AS rn FROM platzi.alumnos ) DELETE FROM platzi.alumnos WHERE id IN ( SELECT id FROM ( SELECT id, ROW\_NUMBER() OVER(PARTITION BY nombre, apellido, email ORDER BY id) AS rn FROM platzi.alumnos ) AS subquery WHERE rn > 1 );
\--Creo que asi es mas sencillo SELECT nombre, apellido, apellido, email,colegiatura, fecha\_incorporacion,carrera\_id,tutor\_id, count (id) FROM platzi.alumnos GROUP BY (nombre,apellido,email,colegiatura, fecha\_incorporacion,carrera\_id,tutor\_id) HAVING COUNT (nombre) >1
```js DELETE FROM platzi.alumnos WHERE id = ( SELECT id FROM ( SELECT id, ROW_NUMBER() OVER( PARTITION BY nombre,apellido,email,colegiatura,fecha_incorporacion,carrera_id,tutor_id ORDER BY id ASC ) AS row FROM platzi.alumnos ) AS duplicados WHERE duplicados.row > 1 ); ```
Prueba de que aun existe los 1000 registros y que el ultimo es el 1000. ![](https://static.platzi.com/media/user_upload/image-870959b3-b5bb-4c90-907a-8dd27b817bd7.jpg)
Verificando que ya no hay duplicados: ![](https://static.platzi.com/media/user_upload/image-8a32d940-3201-40a0-8cdd-3e9d3b041fde.jpg)
Mi solucion para eliminar duplicado. ![](https://static.platzi.com/media/user_upload/image-e987d07a-e1c5-4aa0-80d3-245fb8f6fde1.jpg)
DELETE FROM platzi.alumnos WHERE id = ( SELECT ID FROM ( SELECT ID, ROW\_NUMBER() OVER( PARTITION BY nombre, apellido, email ORDER BY id ASC )AS row FROM platzi.alumnos )AS duplicates WHERE duplicates.row >1 )
SELECT *descrip* || ', ' || *programa* AS *descripcion\_programa*, COUNT(\*) as *contar* FROM *otratabla* GROUP BY *descirp*, *programa* HAVING COUNT(\*) > 1;
Solucion del reto: select \* from platzi.alumnos where (date\_part('year', fecha\_incorporacion)) = 2019 and (date\_part('month', fecha\_incorporacion)) = 05;```html select * from platzi.alumnos where (date_part('year', fecha_incorporacion)) = 2019 and (date_part('month', fecha_incorporacion)) = 05; ```

Reto de la clase

DELETE
FROM platzi.alumnos
Where id IN (
	SELECT id
	FROM (
		SELECT 
			id,
			ROW_NUMBER() OVER (
				PARTITION BY 
					nombre,
					apellido,
					email,
					fecha_incorporacion,
					carrera_id,
					tutor_id
				ORDER BY id ASC
			) AS row,
			nombre,
			apellido,
			email,
			fecha_incorporacion,
			carrera_id,
			tutor_id
		FROM platzi.alumnos
	) AS duplicados
	WHERE duplicados.row > 1);
Mi aporte ![](https://static.platzi.com/media/user_upload/image-e34b8444-06e1-4a2f-a6a2-8879c6eaa7c1.jpg)
Aquí se explica muy bién las window functions: <https://www.youtube.com/watch?v=y1KCM8vbYe4>
SELECT \* FROM ( SELECT id, ROW\_NUMBER() OVER( PARTITION BY nombre, apellido, email, colegiatura, fecha\_incorporacion, carrera\_id, tutor\_id ORDER BY id asc ) AS row, \* FROM platzi.alumnos ) duplicados WHERE duplicados.row > 1; ```js SELECT * FROM ( SELECT id, ROW_NUMBER() OVER( PARTITION BY nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id ORDER BY id asc ) AS row, * FROM platzi.alumnos ) duplicados WHERE duplicados.row > 1; ``` ```txt ```

Solución al reto

DELETE FROM platzi.alumnos
WHERE id = (
    SELECT id
    FROM (
        SELECT
        ROW_NUMBER() OVER(
            PARTITION BY
                nombre,
                apellido,
                email,
                colegiatura,
                fecha_incorporacion,
                carrera_id,
                tutor_id
            ORDER BY id ASC
            AS row,
        *
        FROM platzi.alumnos
    ) AS duplicados
    WHERE duplicados.row > 1
);
📝 A continuación dejo una de las posibles soluciones al reto de esta clase: ```js DELETE FROM platzi.alumnos USING ( SELECT id AS idx, ROW_NUMBER() OVER( PARTITION BY nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id ORDER BY id ASC ) AS row FROM platzi.alumnos ) AS duplicados WHERE duplicados.idx = id AND duplicados.row > 1 ``` Intenté hacer el delete utilizando un `INNER JOIN` de la tabla `alumnos` con la subquery, pero en PostgreSQL no es posible, en su lugar se utiliza la clausula `USING` donde puede ir una tabla común y corriente o bien una sub consulta, al final la clausula `WHERE` es la condición que sustituye a `ON` de un `JOIN`.
Solución sencilla SELECT \* FROM platzi.alumnos WHERE (EXTRACT(YEAR FROM fecha\_incorporacion)) = 2018 AND EXTRACT(MONTH FROM fecha\_incorporacion) = 05
entiendo el poder de las subconsultas pero no siempre son necesarias. Esta es mi alternativa al primer código que realiza el profesor: ```js select id, count(*) numeroCasos from platzi.alumnos group by id having count(*)>1; ```
```js DELETE FROM platzi.alumnos WHERE id = ( SELECT id FROM ( SELECT ROW_NUMBER() OVER( PARTITION BY nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id ORDER BY id asc ) AS row, * FROM platzi.alumnos ) duplicados WHERE duplicados.row > 1 ); ```
Esta es una versión un poco menos compleja para ver los duplicados: ```txt SELECT * FROM ( SELECT *, COUNT(*) OVER(PARTITION BY email) AS copias FROM platzi.alumnos) AS loquesea WHERE copias > 1; ```Con la ventaja adicional de que vemos cada uno de los registros duplicados con todas sus columnas, no solo el conteo. Y para borrarlos si es con código parecido al del profesor: ```txt SELECT * FROM platzi.alumnos WHERE id IN ( SELECT id FROM ( SELECT id, ROW_NUMBER() OVER (PARTITION BY email) AS copias FROM platzi.alumnos ) t WHERE t.copias > 1 ); ```SELECT \* FROM platzi.alumnos WHERE id IN ( SELECT id FROM ( SELECT id, ROW\_NUMBER() OVER (PARTITION BY email) AS copias FROM platzi.alumnos ) t WHERE t.copias > 1 );
SELECT \* FROM platzi.alumnos WHERE((DATE\_PART('YEAR', fecha\_incorporacion))= 2018 AND (DATE\_PART('MONTH', fecha\_incorporacion) = 05));
<u>SELECT \*</u> <u>FROM platzi.alumnos</u> <u>WHERE((DATE\_PART('YEAR', fecha\_incorporacion))= 2018 AND</u> <u>(DATE\_PART('MONTH', fecha\_incorporacion) = 05));</u>
Aqui la tarea: ![](https://static.platzi.com/media/user_upload/Screenshot%202024-04-18%2012.25.17-13b52826-2b1c-4e32-a136-de6c6ebaa68a.jpg)
Soluciones alternativas para encontrar los duplicados con **SQL Server** ya que con :: no existe en SQL Server: ```js SELECT nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id, COUNT (*) as conteo FROM platzi.alumnos GROUP BY nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id HAVING COUNT (*)>1; ``` Otra alternativa utilizando el PARTITION BY es: ```js SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id ORDER BY id ASC ) AS conteo FROM platzi.alumnos ) AS duplicados WHERE duplicados.conteo > 1; ```
Query: select nombre,apellido,email,count(\*) as duplicados from platzi.alumnos group by nombre,apellido,email having count(\*) > 1;
select \* from ( select \*, date\_part('YEAR',fecha\_incorporacion) as anio\_incorporacion, date\_part ('MONTH', fecha\_incorporacion) as mes\_incorporacion from platzi.alumnos)as alumnos\_con\_anio where anio\_incorporacion=2020 and mes\_incorporacion=05;
DELETE FROM platzi.alumnos WHERE id IN ( SELECT id FROM ( SELECT id, ROW\_NUMBER() OVER( PARTITION BY nombre, apellido, email, colegiatura, fecha\_incorporacion, carrera\_id, tutor\_id ORDER BY id ASC) AS rowdup FROM platzi.alumnos ) AS dups WHERE dups.rowdup > 1);
`SELECT * FROM platzi.alumnos ` `WHERE (DATE_PART('MONTH',fecha_incorporacion) = 05) AND (DATE_PART('YEAR',fecha_incorporacion) = 2018);` `SELECT *` `FROM (` `SELECT *, (DATE_PART('YEAR',fecha_incorporacion)) AS anio_incorporacion,` `(DATE_PART('MONTH',fecha_incorporacion)) AS mes_incorporacion` `FROM platzi.alumnos` `)` `WHERE anio_incorporacion = 2018 AND mes_incorporacion = 05;`
DELETE FROM platzi.alumnos WHERE id IN ( SELECT id FROM ( SELECT id, ROW\_NUMBER() OVER ( PARTITION BY nombre, apellido, email, colegiatura, fecha\_incorporacion, carrera\_id, tutor\_id ORDER BY id ASC ) AS row FROM platzi.alumnos ) AS duplicados WHERE duplicados.row > 1 )
select \* from ( select \*, date\_part ('month', fecha\_incorporacion)as mes\_incorporacion, date\_part ('year', fecha\_incorporacion) as annio\_incorporacion from alumnos ) as alumnos\_con\_annio where mes\_incorporacion = 05 and annio\_incorporacion = 2020
SELECT *
FROM platzi.alumnos
WHERE EXTRACT(MONTH FROM fecha_incorporacion) = 5
  AND EXTRACT(YEAR FROM fecha_incorporacion) = 2018;
`SELECT * ` `FROM (` `SELECT *,` `DATE_PART('YEAR', fecha_incorporacion) AS anio_incorporation,` `DATE_PART('month', fecha_incorporacion) AS mes_incorporation` `FROM platzi.alumnos` `)` `AS alumnios_anio` `WHERE anio_incorporation =2020 ` `and mes_incorporation = 5 ;`
```txt ``````js SELECT * FROM ( SELECT *, DATE_PART('YEAR', fecha_incorporacion) AS anio_incorporation, DATE_PART('month', fecha_incorporacion) AS mes_incorporation FROM platzi.alumnos ) AS alumnios_anio WHERE anio_incorporation =2020 and mes_incorporation = 5 ; ```SELECT \* FROM ( SELECT \*, DATE\_PART('YEAR', fecha\_incorporacion) AS anio\_incorporation, DATE\_PART('month', fecha\_incorporacion) AS mes\_incorporation FROM platzi.alumnos ) AS alumnios\_anio WHERE anio\_incorporation =2020 and mes\_incorporation = 5 ;
```js SELECT * FROM platzi.alumnos WHERE EXTRACT(YEAR FROM fecha_incorporacion)=2018 and EXTRACT(MONTH FROM fecha_incorporacion)=05; SELECT * FROM ( SELECT *, EXTRACT(YEAR FROM fecha_incorporacion) as AnioIncorporacion, EXTRACT(MONTH FROM fecha_incorporacion) as MonthIncorporacion FROM platzi.alumnos ) AS alumnos_with_mont_and_year WHERE AnioIncorporacion=2018 and MonthIncorporacion=05; ```SELECT \* FROM platzi.alumnos WHERE EXTRACT(YEAR FROM fecha\_incorporacion)=2018 and EXTRACT(MONTH FROM fecha\_incorporacion)=05; SELECT \* FROM ( SELECT \*, EXTRACT(YEAR FROM fecha\_incorporacion) as AnioIncorporacion, EXTRACT(MONTH FROM fecha\_incorporacion) as MonthIncorporacion FROM platzi.alumnos ) AS alumnos\_with\_mont\_and\_year WHERE AnioIncorporacion=2018 and MonthIncorporacion=05;
pero digamos en el caso de control de inventarios, siempre vamos a tener datos repetidos pero con diferente fecha de ingreso, en ese caso como se controlaría los datos repetidos :(
Gracias, muchas opciones, muchas explicaciones, muchos aportes
```txt --ALUMNOS QUE SE INCORPORARON EN MAYO DEL 2018 SELECT* FROM ( SELECT *, DATE_PART('MONTH',fecha_incorporacion) AS mes_incorporacion, DATE_PART('YEAR',fecha_incorporacion) AS anio_incorporacion FROM PLATZI.alumnos ) as alumnos_con_fecha WHERE mes_incorporacion=5 and anio_incorporacion=2018 ```--ALUMNOS QUE SE INCORPORARON EN MAYO DEL 2018 SELECT\* FROM ( SELECT \*, DATE\_PART('MONTH',fecha\_incorporacion) AS mes\_incorporacion, DATE\_PART('YEAR',fecha\_incorporacion) AS anio\_incorporacion FROM PLATZI.alumnos ) as alumnos\_con\_fecha WHERE mes\_incorporacion=5 and anio\_incorporacion=2018

Ejercicio de tarea:

DELETE FROM platzi.alumnos
WHERE id IN (
	SELECT id
	FROM (
		SELECT id,
		ROW_NUMBER() OVER(
			PARTITION BY
				nombre,
				apellido,
				email,
				colegiatura,
				fecha_incorporacion,
				carrera_id,
				tutor_id
			ORDER BY id ASC
		) AS row
		FROM platzi.alumnos
	) AS duplicados
	WHERE duplicados.row > 1
);
Este tema es muy bueno, pero me gustaría saber ¿Qué tan eficientes son estas estrategias en ambientes en donde se tienen grandes cantidades de datos?
::

Reto resuelto, bastante intuitivo.

DELETE FROM alumnos
WHERE id IN (
	SELECT id FROM (SELECT ROW_NUMBER() OVER(PARTITION BY nombre,apellido,email,colegiatura,fecha_incorporacion,carrera_id,tutor_id ORDER BY id) AS count_row, 
							* FROM alumnos) AS duplicados
	WHERE count_row > 1
)
Esta es mi solucion a la eliminacion de la fila duplicada: ```js DELETE FROM platzi.alumnos WHERE id = ( SELECT id FROM ( SELECT * FROM ( SELECT id, ROW_NUMBER() OVER( PARTITION BY nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id ORDER BY id ASC ) AS row--, --* FROM platzi.alumnos ) AS duplicados WHERE duplicados.row > 1 ) ); ```
Mi solucion al reto de la clase pasada: ```js SELECT * FROM platzi.alumnos WHERE (DATE_PART('YEAR', fecha_incorporacion)) = 2019 AND (DATE_PART('MONTH', fecha_incorporacion)) = 5; ```
select \* from ( select \*, extract(year from (fecha\_incorporacion)) as ano, extract(month from (fecha\_incorporacion)) as mes from platzi.alumnos ) as ano1 where ano = 2020 and mes= 5;

ELIMINACION DE LOS REGISTROS DUPLICADOS

CONSULTA DE LOS REGISTROS DUPLICADOS:

Mi solucion al ejercicio:

Después de tantos intentos pude entenderle, esta es mi solución:

-- Eliminar duplicados con subquery
DELETE FROM platzi.alumnos
WHERE id IN (
	SELECT id
	FROM (
		SELECT id,
		ROW_NUMBER() OVER(
			PARTITION BY
				nombre,
				apellido,
				email,
				colegiatura,
				fecha_incorporacion,
				carrera_id,
				tutor_id
			ORDER BY id ASC
		)AS row
		FROM platzi.alumnos
	) AS duplicados
	WHERE duplicados.row > 1); 

Solución al reto:

DELETE FROM platzi.alumnos
WHERE id IN (
    SELECT id
    FROM (
        SELECT id,
            ROW_NUMBER() OVER (
                PARTITION BY nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id
                ORDER BY id
            ) AS row_num
        FROM platzi.alumnos
    ) AS subquery
    WHERE subquery.row_num > 1
);

mi aporte

DELETE FROM platzi.alumnos
WHERE id IN (
    SELECT id
    FROM (
        SELECT id,
               ROW_NUMBER() OVER (
                   PARTITION BY 
				   nombre, 
				   apellido, 
				   email, 
				   colegiatura, 
				   fecha_incorporacion, 
				   carrera_id, 
				   tutor_id
                   ORDER BY id ASC
               ) AS row
        FROM platzi.alumnos
    ) AS duplicado
    WHERE duplicado.row > 1
);