Query Ejercicio:
insert into platzi.alumnos (id, nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id) values (1000, 'Pamelina', null, 'pmylchreestrr@salon.com', 4800, '2020-04-26 10:18:51', 12, 16);
Query de inserción
insert into platzi.alumnos (id, nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id) values (1001, 'Pamelina', null, 'pmylchreestrr@salon.com', 4800, '2020-04-26 10:18:51', 12, 16)
Query Ejercicio:
insert into platzi.alumnos (id, nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id) values (1000, 'Pamelina', null, 'pmylchreestrr@salon.com', 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, 'pmylchreestrr@salon.com', 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
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.
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 :

Ruiz Julieth
Emmi Raffo
Ruiz Julieth
Carlos Contreras
karen gonzalez
Juan Esteban Bolívar Ferrer
frluenga
karen gonzalez
Elisa Almazán
Víctor Hugo Maya Sandoval
Luis Angel Pasos Montalvo
Nelson Diaz
Miguel Angel Reyes Moreno
Luis Felipe Castaño Villada
John Alexander Ortiz Ramirez
Emmi Raffo
Aaron Fabrizio Calderon Guillermo
Cristian Zerpa
Agustín Alberto Leiva
FELIX DAVID CORDOVA GARCIA
David Carrillo Castillo
Luis Eduardo Sánchez Romero
Ahtziri Cardenas Vela
Jeyson David Vargas Crespo
Luis Angel Vásquez Nepomuceno
Eduard Giraldo Martínez
Andrés Cardona
Juan David Salazar Arias
Mauro Benito Montoya Arenas
Tomas Filippo
Samuel Martínez Hernández
Andres Sanchez
Luis Fernando Vásquez Flores
Rubén Cuello
David Rueda
Anthony Guzman Lopez
Esmeralda Palacios
Agustín Alberto Leiva
Christian David Tovar Tirado
PABLO ARISTIZABAL
Query Ejercicio:
insert into platzi.alumnos (id, nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id) values (1000, 'Pamelina', null, 'pmylchreestrr@salon.com', 4800, '2020-04-26 10:18:51', 12, 16);
Gracias, atentos al id, en clases el id no se repite, debería ser 1001
¡Saludos Emmi!, gracias a ti, me equivoqué, Les comparto el correcto:
insert into platzi.alumnos (id, nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id) values (1001, 'Pamelina', null, 'pmylchreestrr@salon.com', 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 ;)
gracias!!!
Gracias por la aclaración!
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.
gracias!!
¡Muchas gracias, tu explicación me ayudó a entender ese query!
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, 'pmylchreestrr@salon.com', 4800, '2020-04-26 10:18:51', 12, 16);
GRacias!
Por lógica no puede existir 2 correos iguales, por lo tanto realice la actividad en base a eso
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.
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 );
!Genio! Yo por no prestar atención borré todos los registros y tuve que volver al script de sql para insertar toda la info en la tabla xD
¡Á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);
Este borra todos todos los valores duplicados, entiendo que debería borrar solo 1 para que se conserve el valor original
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:
Cristian!!! Muchas gracias, lo pude entender! ( :
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:
Gracias por el aporte, muy útil
chat GPT siempre ayudando
Hola, todavía me confundo con los subqueries, me pueden ayudar porfa a entenderlos mejor...
Muchas gracias...
Hola :)
Hay una clase de subqueries en otro de los cursos de SQL que me gusta mucho, me parece súper clara y sencilla. Te la dejo abajo.
Igual si después de eso tienes dudas o quieres comentar algo, aquí estamos.
https://platzi.com/clases/1272-sql-mysql/11095-insercion-de-datos-usando-queries-anidados/
Lo más probable es que ya hayas entendido el tema, pero dejo el artículo para futuras generaciones.
P.D: Es en inglés, les servirá para practicar
Alguien me podría explicar el OVER() que función cumple? por fa :)
Primero que nada debes recordar que el proposito de row_number es asignar un numero a cada fila, empezando desde 1 y avanzando de 1 en 1. Over le indica a la función row_number sobre cuál grupo de registros hacer la numeración de las filas. imagina que tienes una base de datos (BD) con 100 registros de ciudades y se repiten siempre 3 ciudades, con over (partitition by city) habrá una agrupación por ciudad, es decir, tendras 3 grupos de registros sobre los cuales hacer la numeración.
Si no pusieras nada en over() simplemente numerarías de nuevo toda la base de datos pues no habría un criterio sobre el cual partir la BD.
Gracias Juan. Tu comentario aclaro mis dudas.
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!
Este es el comentario que me salvo!
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```
Hola a todos:
En mi caso le apliqué una pequeña modificación para realizar la agrupación (sección GROUP BY), como se asigna el nombre "items" al conjunto de datos requeridos, ese nombre es el utilizado para agrupar por el conjunto de campos.
A continuación, un ejemplo:
SELECT ( nombre, apellido, email, colegiatura, fecha_incorporacion, carrera_id, tutor_id ) :: text AS items, COUNT(id) :: integer AS cantidad FROM platzi.alumnos GROUP BY items HAVING COUNT(*) > 1;
Nota: En el SELECT se utilizó el campo <<id>> únicamente para mejorar la visualización en la plataforma de Platzi. En pgadmin o consola se puede usar el caracter (*).
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);```
vaya nivel de abstracción! yo aún no digiero bien los subqueries
Si no entendiste el último código, no te preocupes. Creo que el profesor se emocionó un poco y se adelantó con la teoría 😅.
En las últimas clases del curso se profundiza con los temas: Window functions, Particiones y agregación
Te dejo un video que me ayudó a introducirme en las funciones de ventana:
No entendí muy bien la funcionalidad de los '::' , o sea entiendo para que sirven en este caso pero no como se podrían usar en otras aplicaciones o cual es su finalidad
Es para hacer la comparativa mas facil, ya que es solo texto