Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Eliminacion de duplicados (https://www.clubdelphi.com/foros/showthread.php?t=67550)

sizne 22-04-2010 20:07:52

Eliminacion de duplicados
 
Hola Foreros:

Les planteo lo siguiente(con Base de Datos SQL Server):
Form1-Tabla1-DBGrid1-DataSource1
Form2-Tabla2-DBGrid2-DataSource2

Una suposición: Teniendo 3 pasos a), b) y c).

a) Ingreso 3 registros en el Form1.

1Registro-XX1
2Registro-XX2
3Registro-XX3

Estos 3 registros los copio al Form2 (Tabla2), luego elimino los registros del Form1.

b) Ahora ingreso 4 registros en el Form1.
1Registro-XX4
2Registro-XX3
3Registro-XX5
4Registro-XX6

Estos 4 registros los copio al Form2 (Tabla2), luego elimino los registros del Form1.
(...Y asi sucesivamente....)

Aqui el detalle:
c) Cuando copio los registros, en el Form2 debo realizar una eliminacion de todos aquellos que se hayan duplicados, es decir; se debe eliminar el primer registro encontrado duplicado.

Como verán este registro (3Registro-XX3) se repite (2Registro-XX3).

Lo que significa que debo eliminar: 3Registro-XX3
Y mantener el registro : 2Registro-XX3

Estas elminaciones se realizan en el Form2 (Tabla 2), que esta relacionado con el DataSource2 el DBGrid donde se vizualizan tooodas las copiadas (Incluyendo las duplicadas)

Puedo eliminar del DBGrid, el seleccionado, el primer o el ultimo registro; pero no sé cómo hacer para eliminar el primer duplicado encontrado, ya que el segundo es el que quiero que se mantenga.

Graaacias.

ecfisa 22-04-2010 22:28:35

Hola sizne.

Para eliminar los duplicados en "Tabla2" podés usar:
Código:

DELETE FROM Tabla2 a
WHERE Campo_ID > (SELECT MIN(Campo_ID) FROM Tabla2 b
WHERE b.Campo1 = a.Campo1);

Fijate, que en la cláusula WHERE del ejemplo sólo verifico por un campo.
Si queres evaluar por más de un campo tendrías que usar en la cláusula WHERE:
Código:

WHERE b.Campo1 = a.Campo1 AND b.Campo2 = a.Campo2 AND ...
Saludos.

sizne 23-04-2010 00:57:27

Hola ecfisa,
Los datos que puse son solo ejemplos, en si no son cantidades.. (MIN...)
son palabras (siglas de Materias que vuelven a programarse en otra gestion cuando se aplazan, por eso en la Tabla2, se repetiran, cosa que ahi tengo que hacer una limpieza y eliminar SOLO el primer registro duplicado).

Espero me entiendas :o

Gracias!!!

ecfisa 24-04-2010 01:34:32

Hola sizne.

Si, te entendí bién la primera vez. Usá el primer ejemplo que te puse y eliminará los duplicados. (por supuesto cambiá los nombres de campo que puse por los tuyos...);)

Saludos.

Nota: Borré unos comentarios erroneos en el primer post: "DELETE Campos_Deseados FROM" en su lugar va "DELETE FROM", el error fue por que hice la prueba con SELECT y copie y pegue... perdón.

sizne 30-04-2010 16:06:32

Hola ecfisa, gracias por responder y explicar tan bien ;).

Con tu ayuda hice el el siguiente codigo
Cita:

DELETE FROM BDmaterias
WHERE IdM = (SELECT MIN(IdM) FROM BDmaterias b
WHERE b.CodigoM = CodigoM and CalificacionM='Reprobado')
Hice las pruebas respectivas, y pues solo me elimina todos aquellos que sean reprobados una cada ejecucion, aunque no sean igual de CodigoM....

Cita:

DELETE FROM BDmaterias a
WHERE IdM > (SELECT MIN(IdM) FROM BDmaterias b
WHERE b.CodigoM = a.CodigoM and a.CalificacionM='Reprobado')
Aqui me aparecio el error de sintaxis cerca de 'a' y cuando lo elimine, pues me lo eliminaba todos los registros pero menos el menor (IdM=1). Por ello opte por el otro, solo q no resulta como deseo... :(


No sé como hacerlo para salga como quiero, solo eliminar los primeros duplicados y que sean reprobados.

Saludos!

sizne 30-04-2010 20:54:03

Holas...
Miren estuve haciendo lo siguiente para mi duda... pero me los elimina todos los "reprobados" sin importar que haya o no duplicados :confused:
Cita:

DELETE FROM BDmaterias
WHERE IdM IN
(SELECT IdM
FROM BDmaterias b
WHERE NombreM = b.NombreM and (CodigoM=b.CodigoM)and
(CalificacionM='Reprobado')
...alguien???

ecfisa 01-05-2010 03:44:06

Hola de nuevo sizne.
Hoy con un poco más de tiempo, revisé a fondo el código anterior, cosa que no hice antes por carecer de él.:(
Y sí, efectivamente no hace lo que deseas.

Ahora bién, hice una tabla en interbase con los campos involucrados, y la cargué de la siguiente forma:
Código:

IdM  CodigoM  CalificacionM
-----------------------------
1    A        R            (abreviando...)
2    A        R
3    B        R
4    C        R
5    B        R            (mal bicho el profe ...)

La consulta la hice con SELECT para visualizar el resultado (si lo borro difícilmente lo vea):
Código:

IdM  CodigoM  CalificacionM
-----------------------------
1    A        R
3    B        R

Es decir que si cambiamos SELECT por DELETE , esos registros son los que se eliminarán. Por lo tanto
tenemos nuestro problema solucionado.

En definitiva la consulta queda así:
Código:

SELECT * FROM PRUEBA   
WHERE IdM NOT IN(
SELECT MAX(IdM) FROM PRUEBA
GROUP BY CodigoM, CalificacionM)

Fijate que usando MAX(IdM) elimina las primeras apariciones de repetición y usando MIN(IdM), elimina las repeticiones posteriores
Y por supuesto cambiá 'SELECT * FROM' por 'DELETE FROM', al menos si queres que borre...;)

Saludos.

sizne 01-05-2010 20:55:08

Hola ecfisa, gracias eh!!!
Cambie unas cositas en el ejemplo
Código:

IdM  CodigoM  CalificacionM
-----------------------------
1    A        Reprob            (abreviando...)
2    A        Aprob
3    B        Reprob
4    C        Reprob
5    B        Reprob            (mal bicho el profe ...)

En este caso quiero que solo me de resultado:
Código:

IdM  CodigoM  CalificacionM
-----------------------------
2    A        Aprob
4    C        Reprob
5    B        Reprob

Como se vé solo elimina los primeros datos que fueron ingresados, sin importar la calificacionM.
Lo que hice fue lo siguiente en Delphi, funciona pero quiero reducir el codigo y que sea en menor tiempo la ejecucion....y en una sola tabla el recorrido.
Código Delphi [-]
procedure TFKardexM.verificarClick(Sender: TObject);
var i,j:integer;
begin
  i:=0;
  materia.First;
  while i< materia.RecordCount do
    begin
      i:=i+1;
      j:=0;
      materiaT.First;
      while j < materiaT.RecordCount do
      begin
        j:=j+1;
        if (materiaCodigoM.Text  = materiaTCodigoM.Text) then
          begin
            ShowMessage('Son iguales materia '+materiaCodigoM.Text);
            ShowMessage('Son iguales materiaT '+materiaTCodigoM.Text);
            ShowMessage('eliminara en AmateriaT);
            materiaT.Delete;
          end;
      materiaT.Next;
      end;
    materia.Next;
    end;
end;

Aqui estoy usando dos tablas, asi recorro uno por uno y comparo con cada registro de la OTRA tabla.
Pero si fuese solo en una tabla....ya no puedo usar el FIRST,NEXT para comparar....

Saludos...

ecfisa 01-05-2010 22:17:23

Hola sizne.

A ver...
¿ Lo que queres es que se eliminen las apariciones de registros duplicados cuya calificacion sea 'Reprobado' ?

Si es eso bastaría con modificar el código sql así :
Código:

DELETE FROM PRUEBA
WHERE IdM NOT IN(
SELECT MAX(IdM) FROM PRUEBA
GROUP BY CodigoM)
AND CalificacionM = 'Reprob'

Saludos.


La franja horaria es GMT +2. Ahora son las 15:21:09.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi