none
como eliminar registros repetidos ,tengo mas de mil registros....como lo hago? RRS feed

  • Pregunta

  • Holas

    hay un problema en la generación de cursos,y al parecer se ha corrido 2 veces y se han duplicado los cursos,y yo necesito eliminar los cursos repetidos ,solo debe quedar uno solo.

    Con este query saco los alumnos y la cantidad de cursos repetidos,

    ejemplo:

    IdAlumno, IdCurso, cantidadrepetida
    ----------- ----------- -----------
    20823       10379       2
    20823       10599       2
    20823       10601       2
    20823       10608       2
    20823       10613       2
    20823       10617       2
    20823       10619       2
    20823       10625       2
    20823       10638       2
    20823       10639       2
    20823       10641       2
    20823       10647       2
    20823       10662       2
    20823       10668       2
    20909       10599       2
    20909       10600       2
    20909       10608       2
    20909       10609       2
    20909       10624       2
    20909       10625       2
    20909       10640       2
    20909       10642       2
    20932       10610       2
    20932       10633       2
    20932       10634       2
    20932       10641       2
    23272       10401       2
    23272       10404       2
    23272       10497       2
    23272       10600       2
    23272       10624       2
    23272       10625       2
    23272       10633       2
    23272       10635       2
    23272       10661       2
    23272       10664       2
    23272       10679       2
    23277       10631       2
    23277       10632       2
    23277       10633       2
    23277       10634       2
    23277       10635       2
    23277       10636       2
    23277       10637       2
    23277       10638       2
    23277       10639       2
    23277       10640       2
    23277       10641       2
    23277       10642       2
    23277       10643       2
    23277       10644       2
    23277       10645       2
    23277       10646       2
    23277       10647       4
    23277       10648       2

    select IdAlumno,IdCurso,COUNT(1) from alumnocurso
    where idmatricula in (select idmatricula
    from Matricula
    where IdPeriodo = 444
    and estado = 'N')
    group by IdAlumno,IdCurso
    having COUNT(1)>1
    order by 1

    El query de arriba seria mi universo,donde esta el curso 2 veces,como podria hacer para que me deje solo un curso de ese alumno?

    ayuda u_u


    Desarrolladora


    • Editado Rosita_Lima jueves, 29 de marzo de 2012 20:23
    jueves, 29 de marzo de 2012 20:17

Respuestas

  • Hola,

    Vea este código,

    primero prueba com el Select despues delete.

    -- Select
    WITH CTE_DELET
    AS (
    select ROW_NUMBER() OVER (PARTITION BY IdAlumno,IdCurso) As delAlumno from alumnocurso
    where idmatricula in (select idmatricula
    from Matricula
    where IdPeriodo = 444
    and estado = 'N')
    )
    
    SELECT * FROM CTE_DELET
    WHERE delAlumno > 1
    
    -- delete
    WITH CTE_DELET
    AS (
    select ROW_NUMBER() OVER (PARTITION BY IdAlumno,IdCurso) As delAlumno from alumnocurso
    where idmatricula in (select idmatricula
    from Matricula
    where IdPeriodo = 444
    and estado = 'N')
    )
    
    DELETE FROM CTE_DELET
    WHERE delAlumno > 1
    Saludos,
    • Marcado como respuesta Rosita_Lima jueves, 29 de marzo de 2012 22:32
    jueves, 29 de marzo de 2012 20:37
  • A partir de SQL Server 2005 se introdujeron dos nuevas caracteristicas, en este caso las implementamos en conjunto, la primera se denomina Common Table Expression (CTE) o expresion de tabla común, estas te permiten por decirlo asi manejar de forma mas transparentes algunas operaciones como por ejemplo la creacion de consultas recursivas.

    Sintaxis Modelo:

    ;
    WITH NombreCTE (Columna 1,2..n)  
    (
    SELECT * FROM MiTabla
    )
    SELECT * FROM NombreCTE

    Antes del WITH debe haber un ";", de ahi que las buenas prácticas sugieren que toda instrucción T-SQL termine con este.  Luego de definir el nombre de tu CTE puedes (es opcional) indicar las columnas que este contendra, posteriormente puedes referenciar (seguido) tu CTE.

    Las funciones de ranqueo consisten en un grupo de funciones que te permiten establecer un posición en base a la agrupación y ordenamiento establecido, estas funciones son ROW_NUMBER(),RANK, RANK_DENSE,NTITLE.  En este ejemplo la función de rankeo ROW_NUMBER() permite establecer un consecutivo basado en particiones o agrupamiento, en tu caso era a partir de dos columnas.

    Imagina que le indicas al motor que te posicione las filas por estos grupos, internamente el te retorna: 1,2,3.....N.   Como los criterios de agrupación se basaban en campos que tu sabes estan duplicados entonces te muestra el grupo y su posición, al incluirlo dentro de un CTE te da la opción de consultar tu tabla CTE y si es mayor que 1, entonces lo elimina, es decir aquellos que estan duplicados.

    Algunos enlaces de interes:

    http://msdn.microsoft.com/es-es/library/ms175972.aspx

    http://blogs.msdn.com/b/craigfr/archive/2008/03/19/ranking-functions-row-number.aspx

    Cualquier duda con gusto te apoyamos.


    "How many years can some people exist before they're allowed to be free" Bob Dylan Email: info@geohernandez.com Blog: geeks.ms/blogs/ghernandez

    • Marcado como respuesta Rosita_Lima jueves, 29 de marzo de 2012 23:16
    jueves, 29 de marzo de 2012 23:02

Todas las respuestas

  • Puedes probar con este código:

    WITH MiCTE
    (
     SELECT ROW_NUMBER() OVER (PARTITION BY IdAlumno,IdCurso) As SecId
     FROM Matricula
     WHERE IdPeriodo=444 and estado='N'
    )
    DELETE MiCTE
    WHERE SecId >1

    Igual te recomiendo que primero realices la prueba (no pude probarla y lo hice a mano alzada) quitando el DELETE y realizando un SELECT para verificar las filas que te son devueltas.

    Cualquier duda con gusto te apoyamos.


    "How many years can some people exist before they're allowed to be free" Bob Dylan Email: info@geohernandez.com Blog: geeks.ms/blogs/ghernandez

    jueves, 29 de marzo de 2012 20:30
  • Puedes probar con este código:

    WITH MiCTE
    (
     SELECT ROW_NUMBER() OVER (PARTITION BY IdAlumno,IdCurso) As SecId
     FROM Matricula
     WHERE IdPeriodo=444 and estado='N'
    )
    DELETE MiCTE
    WHERE SecId >1

    Igual te recomiendo que primero realices la prueba (no pude probarla y lo hice a mano alzada) quitando el DELETE y realizando un SELECT para verificar las filas que te son devueltas.

    Cualquier duda con gusto te apoyamos.


    "How many years can some people exist before they're allowed to be free" Bob Dylan Email: info@geohernandez.com Blog: geeks.ms/blogs/ghernandez

    hola,

    gracias x tu ayuda...

    probando el select dentro del parentesis,ocurre un problema:

    Msg 4112, Level 15, State 1, Line 1
    The ranking function "ROW_NUMBER" must have an ORDER BY clause.


    Desarrolladora

    jueves, 29 de marzo de 2012 20:37
  • Hola,

    Vea este código,

    primero prueba com el Select despues delete.

    -- Select
    WITH CTE_DELET
    AS (
    select ROW_NUMBER() OVER (PARTITION BY IdAlumno,IdCurso) As delAlumno from alumnocurso
    where idmatricula in (select idmatricula
    from Matricula
    where IdPeriodo = 444
    and estado = 'N')
    )
    
    SELECT * FROM CTE_DELET
    WHERE delAlumno > 1
    
    -- delete
    WITH CTE_DELET
    AS (
    select ROW_NUMBER() OVER (PARTITION BY IdAlumno,IdCurso) As delAlumno from alumnocurso
    where idmatricula in (select idmatricula
    from Matricula
    where IdPeriodo = 444
    and estado = 'N')
    )
    
    DELETE FROM CTE_DELET
    WHERE delAlumno > 1
    Saludos,
    • Marcado como respuesta Rosita_Lima jueves, 29 de marzo de 2012 22:32
    jueves, 29 de marzo de 2012 20:37
  • WITH MiCTE
    (
    SELECT ROW_NUMBER
    () OVER (PARTITION BY IdAlumno,IdCurso ORDER BY idalumno) As SecId
    FROM
    Matricula
    WHERE
    IdPeriodo=444 and estado='N'
    )
    DELETE
    MiCTE
    WHERE
    SecId >1

    Prueba este código de Geovanny ligeramente modificado


    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    jueves, 29 de marzo de 2012 20:40
    Moderador
  • -- Select
    WITH CTE_DELET
    AS (
    select ROW_NUMBER() OVER (PARTITION BY IdAlumno,IdCurso ORDER BY IdAlumno, IdCurso) As delAlumno from alumnocurso
    where idmatricula in (select idmatricula
    from Matricula
    where IdPeriodo = 444
    and estado = 'N')
    )
    
    SELECT * FROM CTE_DELET
    WHERE delAlumno > 1
    
    
    -- delete
    WITH CTE_DELET
    AS (
    select ROW_NUMBER() OVER (PARTITION BY IdAlumno,IdCurso ORDER BY IdAlumno, IdCurso) As delAlumno from alumnocurso
    where idmatricula in (select idmatricula
    from Matricula
    where IdPeriodo = 444
    and estado = 'N')
    )
    
    DELETE FROM CTE_DELET
    WHERE delAlumno > 1

    jueves, 29 de marzo de 2012 20:40
  • Gracias por el aporte Miguel, cometi ese olvido, Rosita puedes probar la consulta. Saludos.

    "How many years can some people exist before they're allowed to be free" Bob Dylan Email: info@geohernandez.com Blog: geeks.ms/blogs/ghernandez

    jueves, 29 de marzo de 2012 21:00
  • Por eso aclaré que el código es tuyo :). Todos podemos olvidar partes cuando escribimos al vuelo...

    Comparte lo que sepas, aprende lo que no sepas (FGG)
    portalSQL
    El rincón del DBA

    jueves, 29 de marzo de 2012 21:02
    Moderador
  • Gracias Miguel :-)  , por supuesto que a todos nos puede pasar.  Saludos

    "How many years can some people exist before they're allowed to be free" Bob Dylan Email: info@geohernandez.com Blog: geeks.ms/blogs/ghernandez

    jueves, 29 de marzo de 2012 21:07
  • Hola gracias

    al probar,veo que ya no existe los duplicados =)

    pero tengo un problemita,es que no entiendo la sintaxis,de como funciona...sobre todo aqui:

    WITH CTE_DELET
    AS (
    select ROW_NUMBER() OVER (PARTITION BY IdAlumno,IdCurso ORDER BY IdAlumno, IdCurso) As delAlumno from alumnocurso
    where idmatricula in (select idmatricula
    from Matricula
    where IdPeriodo = 444
    and estado = 'N')
    )

    que es eso?porque se le puso en un with,podrian explicarme ,porque no sabia programar asi en sql ...

    suelo programas más en .net por eso desconozco que se uso en la sintaxis de arriba,alguien podria explicarmelo?y en qye tema del sql lo encuentro,.

    gracias

    y si funciono

    slds


    Desarrolladora

    jueves, 29 de marzo de 2012 22:26
  • A partir de SQL Server 2005 se introdujeron dos nuevas caracteristicas, en este caso las implementamos en conjunto, la primera se denomina Common Table Expression (CTE) o expresion de tabla común, estas te permiten por decirlo asi manejar de forma mas transparentes algunas operaciones como por ejemplo la creacion de consultas recursivas.

    Sintaxis Modelo:

    ;
    WITH NombreCTE (Columna 1,2..n)  
    (
    SELECT * FROM MiTabla
    )
    SELECT * FROM NombreCTE

    Antes del WITH debe haber un ";", de ahi que las buenas prácticas sugieren que toda instrucción T-SQL termine con este.  Luego de definir el nombre de tu CTE puedes (es opcional) indicar las columnas que este contendra, posteriormente puedes referenciar (seguido) tu CTE.

    Las funciones de ranqueo consisten en un grupo de funciones que te permiten establecer un posición en base a la agrupación y ordenamiento establecido, estas funciones son ROW_NUMBER(),RANK, RANK_DENSE,NTITLE.  En este ejemplo la función de rankeo ROW_NUMBER() permite establecer un consecutivo basado en particiones o agrupamiento, en tu caso era a partir de dos columnas.

    Imagina que le indicas al motor que te posicione las filas por estos grupos, internamente el te retorna: 1,2,3.....N.   Como los criterios de agrupación se basaban en campos que tu sabes estan duplicados entonces te muestra el grupo y su posición, al incluirlo dentro de un CTE te da la opción de consultar tu tabla CTE y si es mayor que 1, entonces lo elimina, es decir aquellos que estan duplicados.

    Algunos enlaces de interes:

    http://msdn.microsoft.com/es-es/library/ms175972.aspx

    http://blogs.msdn.com/b/craigfr/archive/2008/03/19/ranking-functions-row-number.aspx

    Cualquier duda con gusto te apoyamos.


    "How many years can some people exist before they're allowed to be free" Bob Dylan Email: info@geohernandez.com Blog: geeks.ms/blogs/ghernandez

    • Marcado como respuesta Rosita_Lima jueves, 29 de marzo de 2012 23:16
    jueves, 29 de marzo de 2012 23:02
  • A partir de SQL Server 2005 se introdujeron dos nuevas caracteristicas, en este caso las implementamos en conjunto, la primera se denomina Common Table Expression (CTE) o expresion de tabla común, estas te permiten por decirlo asi manejar de forma mas transparentes algunas operaciones como por ejemplo la creacion de consultas recursivas.

    Sintaxis Modelo:

    ;
    WITH NombreCTE (Columna 1,2..n)  
    (
    SELECT * FROM MiTabla
    )
    SELECT * FROM NombreCTE

    Antes del WITH debe haber un ";", de ahi que las buenas prácticas sugieren que toda instrucción T-SQL termine con este.  Luego de definir el nombre de tu CTE puedes (es opcional) indicar las columnas que este contendra, posteriormente puedes referenciar (seguido) tu CTE.

    Las funciones de ranqueo consisten en un grupo de funciones que te permiten establecer un posición en base a la agrupación y ordenamiento establecido, estas funciones son ROW_NUMBER(),RANK, RANK_DENSE,NTITLE.  En este ejemplo la función de rankeo ROW_NUMBER() permite establecer un consecutivo basado en particiones o agrupamiento, en tu caso era a partir de dos columnas.

    Imagina que le indicas al motor que te posicione las filas por estos grupos, internamente el te retorna: 1,2,3.....N.   Como los criterios de agrupación se basaban en campos que tu sabes estan duplicados entonces te muestra el grupo y su posición, al incluirlo dentro de un CTE te da la opción de consultar tu tabla CTE y si es mayor que 1, entonces lo elimina, es decir aquellos que estan duplicados.

    Algunos enlaces de interes:

    http://msdn.microsoft.com/es-es/library/ms175972.aspx

    http://blogs.msdn.com/b/craigfr/archive/2008/03/19/ranking-functions-row-number.aspx

    Cualquier duda con gusto te apoyamos.


    "How many years can some people exist before they're allowed to be free" Bob Dylan Email: info@geohernandez.com Blog: geeks.ms/blogs/ghernandez

    sé que habia otra manera de hacerlo...era con cursores no?desconocia esta manera... y la bd que trabajamos es sql 2008 r2 ...

    pero eso de los CTE,me parece igual que hacer un select ... en serio hay diferencias?


    Desarrolladora

    jueves, 29 de marzo de 2012 23:17
  • Es posible resolver este tipo de escenarios con cursores, pero estos tienen un pésimo desempeño y no son en absoluto recomendable, en cambio el uso de soluciones orientadas a conjuntos (como este CTE) sí son optimas.  Con lo que mencionas que te parecen igual que un select, en mi opinión representan una versión mejorada y que te brinda opciones de uso muy interesantes, como por ejemplo la construcción de consultas recursivas.

    En este link muestran una serie de escenarios para su uso:

    http://msdn.microsoft.com/en-us/library/ms175972.aspx

    Cualquier otra duda con gusto me puedes escribir.  Saludos.


    "How many years can some people exist before they're allowed to be free" Bob Dylan Email: info@geohernandez.com Blog: geeks.ms/blogs/ghernandez

    viernes, 30 de marzo de 2012 1:59