Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

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 115

Preguntas 11

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

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);

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);

Más información del having => https://www.postgresqltutorial.com/postgresql-having/

Saludos, mi respuesta:

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.

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);

¡Ánimo vas por la mitad!

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

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);```

No me sirvieron los ejemplos en workbench 😦

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```

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
)

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;```

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);

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
);

Esto si me hizo pensar e investigar mucho!

Aqui mi solucion:

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) a
	 WHERE a.row_num >1);

Sólo por curiosidad, las 3 carreras que más tienen estudiantes son:
Ingeniería civil
Ingeniería mecánica
Ciencias políticas

SELECT *
FROM platzi.carreras
WHERE id IN (22,9,28);

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 ;

Hola, antes de empezar la clase intenté crear una consulta que me retornara los duplicados y este fue el resultado;

SELECT *
FROM(
	SELECT nombre, apellido, COUNT(nombre) AS a1, COUNT(apellido) AS apellido_repetido 
	FROM platzi.alumnos
	GROUP BY nombre, apellido
	ORDER BY a1 DESC, apellido_repetido DESC
) AS test 

WHERE a1 >=2;

Comparto el reto de la clase anterior
select* from(SELECT *, date_part(‘YEAR’,fecha_incorporacion)AS YE,
date_part(‘MONTH’,fecha_incorporacion)AS MO
from platzi.alumnos) as alumnos_con_anio
where YE= 2018 and MO=2;

SELECT *
FROM (
SELECT *,
DATE_PART(‘YEAR’, fecha_incorporacion) AS anio_incorporacion,
DATE_PART(‘MONTH’, fecha_incorporacion) AS mes_incorporacion
FROM platzi.alumnos ) AS alumnos_mesyaño
WHERE anio_incorporacion = 2020 AND
mes_incorporacion = 5

DELETE from 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 alumnos 
             ) as duplicados
WHERE duplicados.row > 1);

Desafío:

-- Reto: Borrado de los duplicados

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 (nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id)::text, count(*)
FROM  platzi.alumnos
GROUP BY (nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id)
HAVING COUNT(*) > 1

Utilizando las dos funciones:

SELECT *
FROM platzi.alumnos
WHERE ( DATE_PART('YEAR',fecha_incorporacion)) = 2018
AND EXTRACT(MONTH FROM fecha_incorporacion) = 5

Solucion al ejercicio en MySQL:

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
);

Nota: Puede ser que en MySQL les aparezca el ERROR CODE 1175. para resolver esto solo tienen que desactivar la opcion “SAVE UPDATES”:

1.Go to Edit --> Preferences
2.Click “SQL Editor” tab and uncheck “Safe Updates” check box
3.Click OK.

delete from platzi.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 ASC)as row,*
from platzi.alumnos)as duplicados
where duplicados.row >1);

Aqui esta el resultado del reto no use el PARTITION OVER porque no me quedo claro para que era. Asi que use un JOIN

DELETE FROM platzi.alumnos where id in (SELECT identificador FROM (
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 
	) as a1 
	right join (
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(*),  CASE WHEN COUNT(id)>'0' THEN id end as identificador FROM platzi.alumnos
	GROUP BY id, 
		platzi.alumnos.nombre, 
		platzi.alumnos.apellido, 
		platzi.alumnos.email, 
		platzi.alumnos.colegiatura, 
		platzi.alumnos.fecha_incorporacion, 
		platzi.alumnos.carrera_id, 
		platzi.alumnos.tutor_id 
	)as a2 ON a1.row= a2.row
	where a1.count>1 
	offset 1)

Encontrar rows duplicados usando subqueries y window functions

Encontrar rows duplicados transformandolos en texto y agrupando por todos los campos pero excluyendo el ID

Encontrar rows duplicados transformandolos en texto

Detección de IDs duplicados con una tabla externa y una interna

Inserción de duplicado en la base de datos pero con un id no duplicado

Solución de la tarea de la clase anterior

mejor se filtra por email

select * 
from platzi.alumnos as ou
where (
	select count(*)
	from platzi.alumnos as inr
	where ou.email = inr.email
) > 1

Si usas Snowflake lee esto:

Hola chicos, en algunas clases de este curso ya he publicado variaciones para Snowflake porque la empresa donde trabajo lo utiliza y estoy realizando este curso allí (Pueden probarlo gratis) Algunas Startups de delivery en Colombia lo utilizan.

Para este caso específico ofrezco esta solución

En las window functions normales se debe “anidar” el select de la wf dentro de otro más grande,en snowflake podemos simplificarlo con QUALIFY, basicamente actúa como un where pero para una window function: https://docs.snowflake.com/en/sql-reference/constructs/qualify.html aqui tienen más información de QUALIFY.

SELECT 
    ROW_NUMBER() OVER(
        PARTITION BY
            NOMBRE,
            APELLIDO,
            EMAIL,
            COLEGIATURA,
            FECHA_INCORPORACION,
            CARRERA_ID,
            TUTOR_ID
         ORDER BY ID ASC
        ) AS ROW_COUNT,
    *
FROM ALUMNOS
QUALIFY ROW_COUNT >1;

SI TIENEN DUDAS ESCRIBANME, IGUAL TAMBIÉN ESTOY APRENDIENDO jeje

--Ejercicio del video
delete
from platzi.alumnos
where id in(select platzi.alumnos.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
		   );

Solución al reto, comprobada:

DELETE 
FROM platzi.alumnos AS talumnos
WHERE talumnos.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(‘YEAR’,fecha_incorporacion) AS anio_incorporacion,
DATE_PART (‘MONTH’ , fecha_incorporacion) AS mes_incorporacion
FROM platzi.alumnos
) AS alumnos_con_año_mes
WHERE anio_incorporacion = 2018 AND mes_incorporacion = 05;

RETO

Me tardé pero
¡Aquí está!

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

Hola compañeros estuve tratando de entender Partition By, y a esto llegue por si alguno de ustedes le sirve:
Hasta donde he visto con count, row_number, max y min
En este video pueden encontrar de donde lo aprendi:
https://www.youtube.com/watch?v=6trOvsL80Oo

Mediante el siguiente ejemplo

Mediante un Count , va a contar “sobre de” (OVER ⇒ Sirve para dar la partición de sobre que se va a hacer dicha partición), dentro de OVER se hace la partición con PARTITION BY en este ejemplo es sobre weight_class . Este cuenta cuando el weight_class sea el mismo y se lo asigna como una columna la cual hace el calculo, entonces todos aquellos que tengan el mismo weight_class se cuentan y se le asigna ese valor, en el ejemplo hay 2 con 56, entonces a cada fila se le agrega ese 2 que es el conteo.

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

Ahora para nuestro ejemplo se hace algo similar , sin embargo, va a buscar la similitud exacta de varias columnas y no solo de una, va a asignar un row_number (numero de fila) por cada elemento que encuentre que es igual en nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id y tutor_id esto crea para cada uno de las tuplas un 1 que es su row consecutivo, cuando encuentre un segundo igual le va a asignar el 2

Así se ve el dato repetido:

Así se ve la row cuando aplicamos la ultima sentencia WHERE duplicados.row > 1

Borrar el duplicado

Haciendo uso de la misma lógica

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

Ahora en este ejemplo toma la misma lógica anterior para encontrar esas tuplas pero solo borra la que es mayor a 1, osease el dato con el valor de fila 2, en resumen el repetido.

select *
from platzi.alumnos
where (extract (year from fecha_incorporacion)) = 2020 and
(extract (month from fecha_incorporacion)) = 05;

<delete from platzi.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 ASC) as row ,*
								
								from platzi.alumnos
							
						)as duplicados 
						
						where duplicados.row >1
> 
  • Curiosidad: ¿Cuantas personas tienen el mismo nombre?

SELECT (platzi.alumnos.nombre)::text, COUNT(*)
FROM platzi.alumnos
GROUP BY platzi.alumnos.nombre
ORDER BY COUNT(*) DESC;

En este artículo se explica cómo funciona la sentencia ROW_NUMBER() OVER( PARTITION()):

https://www.postgresqltutorial.com/postgresql-row_number/

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)

MI SOLUCION AL RETO:
SELECT *
FROM platzi.alumnos
WHERE (DATE_PART (‘YEAR’, fecha_incorporacion))= 2018 AND
(DATE_PART (‘MONTH’, fecha_incorporacion))= 5;

Mi solucion al reto:

;WITH Repetidos AS (
SELECT id FROM
(
SELECT id,ROW_NUMBER () OVER (PARTITION BY nombre,apellido,email,colegiatura,fecha_incorporacion,carrera_id,tutor_id ORDER BY id) AS RowNumber
FROM alumnos
) AS A
WHERE RowNumber > 1
)

DELETE A FROM alumnos AS A
	INNER JOIN Repetidos AS R
		ON A.id = R.id

Creo que la manera más corta de poder lograr el delete es de la siguiente manera:

delete from alumnos 
where id in (	select max(id) as id 
			from alumnos group by nombre, apellido, email 							 
                       	having count(*)>1);

Ver duplicado por nombre y email

SELECT platzi.alumno.*
FROM platzi.alumno 
WHERE nombre IN(
			SELECT nombre FROM platzi.alumno
            GROUP BY nombre
            HAVING COUNT(*)>1
            ) AND email IN(
			SELECT email FROM platzi.alumno
            GROUP BY email
            HAVING COUNT(*)>1
            );

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);

Dejo mi aporte que es muy similar al del video, pero me ahorro línea de código a la hora de hacer el group by pasandole el 1 como primer columna.

SELECT cast( 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) as varchar),
		COUNT(*)
FROM platzi.alumnos
GROUP BY 1
HAVING COUNT(*) >1

Espero que les sirva

Propongo dos posibles respuestas al ejercicio de la clase anterior.
Propuesta 1 (63 miliseconds):

SELECT *
	FROM platzi.alumnos
	WHERE DATE_PART('YEAR', fecha_incorporacion) = 2018
	AND DATE_PART('MONTH', fecha_incorporacion) = 05 

Propuesta 2: (67 milisenconds)

SELECT *
FROM (
	SELECT *
	FROM platzi.alumnos
	WHERE DATE_PART('YEAR', fecha_incorporacion) = 2018
	AND DATE_PART('MONTH', fecha_incorporacion) = 05 
) as datos 
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 = 5

Esta fue la única posibilidad que si me dio aunque no me siento orgulloso de ello pues parece código espagueti. Espero encontrar en la siguiente clase una solución mas optima

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
	) AS final
);

Después de romper mucho código SALIO:

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);
DELETE FROM platzi.alumnos where id in (	
	SELECT id_
	FROM (
		SELECT id as 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 solución al reto:

WITH duplicados AS (
    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
)

DELETE FROM platzi.alumnos
WHERE id = (
    SELECT id
    FROM duplicados
    WHERE row > 1
);

Mi query

DELETE FROM platzi.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 ASC) AS row,
			*
		FROM platzi.alumnos) AS duplicados
	WHERE duplicados.row > 1);

Mi solución al reto, el cual elimina el registro y con la sentencia RETURNING nos dice los datos que acaba de eliminar:

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
)
RETURNING *;

DELETE FROM platzi.alumnos
WHERE platzi.alumnos.email = (
SELECT email
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
);

segundo tip,
crear un alias de la selección de campos para no volver a repetir en el group by

-------
SELECT (
	nombre,
	apellido,
	email,
	colegiatura,
	fecha_incorporacion,
	carrera_id,
	tutor_id
)::text AS concat , COUNT(*)
FROM platzi.alumnos
GROUP BY concat;

si quieren traer los nombres de las columnas para escribirlos uno por uno, pensando que tenemos una tabla con muchas columnas

SELECT column_name
FROM information_schema.columns
WHERE table_schema = 'platzi'
AND table_name = 'alumnos';

Duplicados

  • Con un casteo a texto y agrupación con un HAVING (se ejecuta más tarde que el WHERE y permite tener en cuenta valores agregados luego de las agrupaciones)
SELECT (
	platzi.alumnos.nombre,
	platzi.alumnos.apellido,
	platzi.alumnos.colegiatura,
	platzi.alumnos.carrera_id,
	platzi.alumnos.tutor_id
)::text AS datita, COUNT(*)
FROM platzi.alumnos
GROUP BY (
	platzi.alumnos.nombre,
	platzi.alumnos.apellido,
	platzi.alumnos.colegiatura,
	platzi.alumnos.carrera_id,
	platzi.alumnos.tutor_id
)
HAVING COUNT(*) > 1;

  • Con un subquery
SELECT *
FROM(
    SELECT ID,
    ROW_NUMBER() OVER(
        PARTITION BY
            nombre,
            apellido,
            colegiatura,
            carrera_id,
            tutor_id
        ORDER BY ID ASC
    ) AS row, 
    *
    FROM platzi.alumnos
) AS duplicados
WHERE duplicados.row > 1;
start transaction;
delete
from platzi.alumnos as pl
where pl.id= (
select t1.id
from(
		select 
			row_number () over (partition by			
			nombre,
			apellido,
			email,
			colegiatura,
			fecha_incorporacion,
			carrera_id,
			tutor_id
			order by id asc) as ranking,*				
		from platzi.alumnos t2) as t1
	where t1.ranking > 1
	order by 1 desc
	limit 1)
 	commit;

Resultado del ejercicio:

delete from platzi.alumnos 
where id in(select duplicados.id
from (
	select id,
	count(*) 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 platzi.alumnos
where (
extract(year from fecha_incorporacion) = 2019
and extract(month from fecha_incorporacion) = 05
)

;

estudiantes que ingresaron en mayo de 2018

SELECT * FROM alumnos WhERE year(fecha_incorporacion)= 2018 and month(fecha_incorporacion)=5;

Este es un codigo mas reducido y mejor entendible

SELECT  nombre, apellido
FROM platzi.alumnos
GROUP BY nombre,apellido,fecha_incorporacion
having(COUNT(*)>1);

ASI RESOLVI EL RETO ANTERIOR

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

Hola! Comparto la solución al reto.
Los alias juegan un papel importante en este caso, justamente porque estaremos redundando sobre el nombre de los campos:

/*
Solución al reto 
*/

DELETE
FROM
	alumnos
WHERE
	id = (
		SELECT
			dup.id
		FROM
			(
				SELECT
					a.id id2,
					ROW_NUMBER() OVER(
						PARTITION BY a.nombre,
						a.apellido,
						a.email,
						a.colegiatura,
						a.fecha_incorporacion,
						a.carrera_id,
						a.tutor_id
					ORDER BY
						a.id ASC
					) AS ROW,
					*
				FROM
					alumnos a
			) dup
		WHERE
			dup.ROW>1
	);

Mi solución al ejercicio del final

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 row > 1)

Query del reto:

<
DELETE FROM platzi.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 ASC	 
				 ) AS row,
				*
				FROM platzi.alumnos 
) AS duplicados
WHERE duplicados.row > 1 
);

> 

Para insertar el ultimo elemento de manera ‘dinamica’

-- Selecciona la ultima fila de nuestra tabla
SELECT * FROM platzi.alumnos
WHERE id = (
  SELECT MAX(id) FROM platzi.alumnos
);

-- Podemos usar la ultima proyeccion para insertar los valores
INSERT INTO platzi.alumnos (
  id,
  nombre,
  apellido,
  email,
  colegiatura,
  fecha_incorporacion,
  carrera_id,
  tutor_id
)(
  SELECT
    id+1,
    nombre,
    apellido,
    email,
    colegiatura,
    fecha_incorporacion,
    carrera_id,
    tutor_id
  FROM platzi.alumnos
  WHERE id = (
    SELECT MAX(id) FROM platzi.alumnos
  )
);
  1. Seleccionamos la tabla a la que queremos borrar
  2. Vamos a borrar la fila donde el id sea un duplicado
  3. Para encontrar el duplicado se hace un conteo en una columna nueva, sobre los datos de nombre, apellido, etc (con la función PARTITION BY)

Notas cuidados con las redundancias, por eso usamos los alias como duplicados, para que no se confundan los ids

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

usen este para adicionar la otra Pamelina:

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);

el id tiene que ser si o si distinto

Me llevo algo de tiempo entender:

fuente que me ayudo a entener bien PARTITION BY

solucion al reto

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;```

WHERE es lo mismo que HAVING
solo que WHERE: nos condiciona los registros individuales
HAVING: Es la forma de condicionar los registros agrupados, por eso va despues de GROUP BY .
Sin embargo no quiere decir que no pi¿odamos utilizarlos en el mismo query

DELETE 
FROM alumnos
WHERE 
id = (
	SELECT MAX(alumnos.id)
	FROM
		(SELECT email, COUNT(*) TotalRegistrosEmail
			FROM alumnos
			GROUP BY email
			HAVING COUNT(*) > 1) AS temp1,
		alumnos
	WHERE 
	temp1.email = alumnos.email and temp1.TotalRegistrosEmail >= 2	
)```
INSERT 
INTO alumnos 
VALUES (
	(SELECT MAX(id) from alumnos)+1, 
	'Wanda', 
	'Billington', 
	'[email protected]', 
	'4800', NOW()::timestamp, 
	40, 
	26
); 

la diferencia entre where y having es que WHERE se usa para evaluar rows ( filas ), mientras que HAVING se usa para evaluar grupos de filas

DELETE FROM platzi.alumnos
WHERE id =  (SELECT duplicados.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);

Alguno esta usando workbench?? porque el row_number no funciona.

La verdad no pude solo, el comando DELETE me asusta todavía

--Reviso los registros
SELECT COUNT(*)
FROM platzi.alumnos;
--Resultado 1001


--Verifico sin hay registros repetidos
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;
--Aparece un registro repetido

--Eliminar la referencia a "Todos los campos" *
--Modificar el SELECT * por id
--Agregar la sentencia DELETE FROM platzi.alumnos
--Agregar WHERE id IN
--Coloco un LIMIT 1 por seguridad

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
);

--Verificar si hay registros repetidos

Insert de forma más sencilla

INSERT INTO alumnos
SELECT*
FROM alumnos
WHERE ID = 1000;

Al momento de eliminar duplicados hay multiples soluciones. SIn embargo, cuando hayan millones de datos los queries podrían durar horas e incluso días. Hasta el momento lo mas efectivo que he encontrado NO es usar DELETE, es por el contrario insertar los valores distintos en una nueva tabla. El query puede reducirse a unos pocos minutos. Cabe aclarar que primero hay que crear la nueva tabla.

INSERT INTO `newtable`  (fieldid, field1,field2,field3)
SELECT DISTINCT (fieldid, value1, value2,value3) 
FROM oldtable;

era mas fácil versi el email estaba duplicado

SELECT * 
FROM platzi.alumnos
WHERE (EXTRACT(YEAR FROM fecha_incorporacion)) = 2018 AND
(EXTRACT (MONTH FROM fecha_incorporacion)) = 05;```

Respuesta reto dia anterior:

select * from platzi.alumnos
where extract(year from fecha_incorporacion)=2018 and extract(month from fecha_incorporacion)=5

Analizando y Analizando este fue el método que se me ocurrió.

Reto usando la query anterior borrar los registros Duplicados

-- CANTIDAD DE Duplicados menos 1
SELECT COUNT(*) - 1 as num 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 ASC
    ) AS row,
    *
    FROM alumnos
    ) AS duplicados
  WHERE duplicados.row > 1
)

-- borrando todos los duplicados
DROP 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 ASC
    ) AS row,
    *
    FROM alumnos
  ) AS duplicados
WHERE duplicados.row > 1;


-- borrando todos los de id null
DELETE FROM alumnos WHERE id IS NULL;

-- TODOS los ids de los duplicados menos 1
SELECT id 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 ASC
    ) AS row,
    *
    FROM alumnos
    ) AS duplicados
  WHERE duplicados.row > 1
) LIMIT (SELECT COUNT(*) - 1 as num
  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 ASC
    ) AS row,
    *
    FROM alumnos
    ) AS duplicados
  WHERE duplicados.row > 1
))

-- borrando todos los duplicados menos 1 es decir el original
DELETE FROM alumnos WHERE ctid IN (
  SELECT ctid
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 ASC
    ) AS row,
    *
    FROM alumnos
    ) AS duplicados
  WHERE duplicados.row > 1
) LIMIT (SELECT COUNT(*) - 1 as num
  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 ASC
    ) AS row,
    *
    FROM alumnos
    ) AS duplicados
  WHERE duplicados.row > 1
))
)
-- nota ctid es un identificador transaccional de postgreSQL cada fila posee uno unico pero cambia tras una transaccion o actulizacion, funciona para identificar filas durante una transaccion pero para identificacion logica y a largo plazo se deben usar los ids

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 = 05 ;```

Reto: "Seleccionar por año"
Primera forma:

<SELECT *
FROM platzi.alumnos
WHERE (DATE_PART('YEAR', fecha_incorporacion)) = 2018 AND
      (DATE_PART('MONTH', fecha_incorporacion)) = 5
>

Segunda forma:

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

Se que el reto estaba muy fácil, pero no quise dejar de hacerlo:

SELECT *
FROM platzi.alumnos
WHERE DATE_PART('MONTH', fecha_incorporacion) = 5 
AND
DATE_PART('YEAR', fecha_incorporacion) = 2018

Sol:

DELETE FROM platzi.alumnos WHERE id IN (
SELECT	id
FROM (
	SELECT id,
	ROW_NUMBER() OVER(
		PARTITION BY
			apellido,email,colegiatura,fecha_incorporacion,carrera_id,tutor_id
		ORDER BY id asc
	) AS row
	FROM platzi.alumnos
) duplicados
WHERE duplicados.row > 1);
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 reg_duplicados);

Mi solución no tiene mucho que ver con la clase pero funciona

DELETE FROM platzi.alumnos WHERE id =1001;