Ir al contenido


Foto

¿Cómo se puede hacer un delete usando joins?


  • Por favor identifícate para responder
19 respuestas en este tema

#1 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.945 mensajes
  • LocationMéxico

Escrito 16 febrero 2015 - 03:53

Hola amigos,

¿Cómo podría hacerse una sentencia de este tipo en Firebird?



sql
  1.   DELETE empleados
  2.       FROM empleados
  3. INNER JOIN empleadosbaja
  4.         ON empleados.clave = empleadosbaja.clave


  • 0

#2 giulichajari

giulichajari

    Advanced Member

  • Miembros
  • PipPipPip
  • 477 mensajes

Escrito 16 febrero 2015 - 04:48

Pues nunca use un join con un delete, no te funciono lo anterior?

Si tienes la tabla empleados y empleadosbaja, en empleadosbaja luego de declarar la clave foranea idempleado(osea la clave primaria de empleado) colocas un:



delphi
  1. on delete cascade



Esto significa que al eliminar un empleado eliminas los registros que contienen ese empleado de la tabla empleadosbaja
  • 0

#3 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 mensajes
  • LocationMisiones, Argentina

Escrito 16 febrero 2015 - 05:12

JOIN no es una claúsula de DELETE. Según tengo entendido es exclusiva de SELECT. ;)
Para eliminar podrías recurrir a un where con la lista obtenida de un SELECT empleadosbaja y utilizar su clave.
algo así como:



delphi
  1. delete from empleados
  2.   where id_empleado in select id_empleado from empleadosbaja



Saludos
(b) (b)
  • 0

#4 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.945 mensajes
  • LocationMéxico

Escrito 16 febrero 2015 - 07:51

Me explico un poco mejor amigos, aunque el where in funciona, en mi caso debo eliminar en una tabla los registros que cumplan con la condición de tres campos llave resultantantes de una subconsulta. Generalmente para eso en otras bases de datos utilizo inner join pero en Firebird nada más no logro encontrar la forma de hacerlo.

Hace poco comencé a usar firebird y desconozco como funcionan algunas cosas.

Saludos
  • 0

#5 Sergio

Sergio

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.092 mensajes
  • LocationMurcia, España

Escrito 17 febrero 2015 - 03:57

Sería igual pero con mas clausulas "where":



delphi
  1. delete from empleados where id_empleado in (
  2.   select b.id_empleado from empleadosbaja b where b.pais=18 and b.fechaalta<'12.01.2014' )



O si son varios campos los que tienen que cumplir diferentes consultas:



delphi
  1. delete from empleados where
  2.   id_empleado in (select id_empleado from empleadosbaja) and
  3.   pais in (select pais from paises where activo=1)


  • 0

#6 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.945 mensajes
  • LocationMéxico

Escrito 17 febrero 2015 - 10:38

O si son varios campos los que tienen que cumplir diferentes consultas:


delphi
  1. delete from empleados where
  2.   id_empleado in (select id_empleado from empleadosbaja) and
  3.   pais in (select pais from paises where activo=1)



Me parece que en todo caso esta es la mejor opción que tengo... Gracias amigo.


  • 0

#7 genriquez

genriquez

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 539 mensajes
  • LocationCali, Colombia

Escrito 17 febrero 2015 - 06:49

en ciertas oportunidades donde tengo varios campos en la llave primaria, lo que hago es concatenar esto en un texto y realizo la comparación.



delphi
  1. delete from empleados where
  2.   id_empleado || id_ciudad in (select distinct id_empleado || id_ciudad from empleadosbaja)



Algo así, hasta ahora me ha funcionado perfectamente, claro que esto lo trabajo en postgres, pero debe funcionar similarmente en otras bd.

Saludos.
  • 0

#8 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.945 mensajes
  • LocationMéxico

Escrito 18 febrero 2015 - 08:42

en ciertas oportunidades donde tengo varios campos en la llave primaria, lo que hago es concatenar esto en un texto y realizo la comparación.



delphi
  1. delete from empleados where
  2.   id_empleado || id_ciudad in (select distinct id_empleado || id_ciudad from empleadosbaja)



Algo así, hasta ahora me ha funcionado perfectamente, claro que esto lo trabajo en postgres, pero debe funcionar similarmente en otras bd.

Saludos.



Es una solución bastante creativa amigo mio pero no es la más óptima. Me explico:

Cuando realizas búsquedas en campos llave estás aprovechando la optimización del motor al trabajar con campos indexados. Pero cuando concatenas se pierde la ventaja del índice y el motor de base de datos debe recorrer fila por fila comparando los valores para encontrar el rango de filas coincidentes, eso en unos pocos cientos de filas es aceptable pero no cuando trabajas con miles o millones.


  • 0

#9 genriquez

genriquez

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 539 mensajes
  • LocationCali, Colombia

Escrito 18 febrero 2015 - 01:21

Amigo Poliburro

En eso tienes toda la razón, son cuidados que hay que tener, por eso no la había propuesto antes en este foro, pero puede sacar de apuros en algunos casos.

;)

Saludos.
  • 0

#10 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.945 mensajes
  • LocationMéxico

Escrito 18 febrero 2015 - 01:53

Amigo Poliburro

En eso tienes toda la razón, son cuidados que hay que tener, por eso no la había propuesto antes en este foro, pero puede sacar de apuros en algunos casos.

;)

Saludos.


Muy cierto amigo, es al final una solución bastante creativa la que has compartido.
  • 0

#11 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.484 mensajes
  • LocationMallorca

Escrito 19 febrero 2015 - 08:20

en ciertas oportunidades donde tengo varios campos en la llave primaria, lo que hago es concatenar esto en un texto y realizo la comparación.



delphi
  1. delete from empleados where
  2.   id_empleado || id_ciudad in (select distinct id_empleado || id_ciudad from empleadosbaja)



Algo así, hasta ahora me ha funcionado perfectamente, claro que esto lo trabajo en postgres, pero debe funcionar similarmente en otras bd.

Saludos.


Interesante e imaginativa solución, aunque yo lo cambiaría ligeramente por :



delphi
  1. delete from empleados where
  2. id_empleado || '-' || id_ciudad in (select distinct id_empleado || '-' || id_ciudad from empleadosbaja)



Y es que por ejemplo si en empleadosbaja tienes activado para dar de baja el empleado 1 y ciudad 11, resulta que esa consulta te borrará esos empleados, pero también el empleado 11 y ciudad 1.

Ya que 1 || 11 = 11 || 1 = 111

Para evitar eso, pon un separador entre ambos códigos y ya no se pueden confundir : 1-11 es distinto de 11-1.

Saludos.

  • 0

#12 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.484 mensajes
  • LocationMallorca

Escrito 19 febrero 2015 - 08:26


en ciertas oportunidades donde tengo varios campos en la llave primaria, lo que hago es concatenar esto en un texto y realizo la comparación.



delphi
  1. delete from empleados where
  2.   id_empleado || id_ciudad in (select distinct id_empleado || id_ciudad from empleadosbaja)



Algo así, hasta ahora me ha funcionado perfectamente, claro que esto lo trabajo en postgres, pero debe funcionar similarmente en otras bd.

Saludos.



Es una solución bastante creativa amigo mio pero no es la más óptima. Me explico:

Cuando realizas búsquedas en campos llave estás aprovechando la optimización del motor al trabajar con campos indexados. Pero cuando concatenas se pierde la ventaja del índice y el motor de base de datos debe recorrer fila por fila comparando los valores para encontrar el rango de filas coincidentes, eso en unos pocos cientos de filas es aceptable pero no cuando trabajas con miles o millones.


Cierto, pero en este caso que ambos campos a concatenar se encuentran en la misma tabla, puedes realizar un índice con esa expresión.

CREATE INDEX IDX_BUSQUEDA ON EMPLEADOS COMPUTED BY (ID_EMPLEADO || ID_CIUDAD);

Ahora todo depende de que el motor de Firebird sea suficientemente inteligente para detectar al lanzar tu consulta que puedes utilizar este índice (la verdad es que nunca lo he probado, pero si existe es porque lo debe detectar).

NOTA: Aplicando la corrección que sugiero en el mensaje anterior, el índice quedaría :

CREATE INDEX IDX_BUSQUEDA ON EMPLEADOS COMPUTED BY (ID_EMPLEADO || '-' || ID_CIUDAD);

Saludos.

  • 0

#13 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.945 mensajes
  • LocationMéxico

Escrito 19 febrero 2015 - 08:56


Ahora todo depende de que el motor de Firebird sea suficientemente inteligente para detectar al lanzar tu consulta que puedes utilizar este índice (la verdad es que nunca lo he probado, pero si existe es porque lo debe detectar).

NOTA: Aplicando la corrección que sugiero en el mensaje anterior, el índice quedaría :

CREATE INDEX IDX_BUSQUEDA ON EMPLEADOS COMPUTED BY (ID_EMPLEADO || '-' || ID_CIUDAD);

Saludos.



Esto se va poniendo harto interesante. :D

Efectivamente amigo marc, esto optimizaría la consulta y aunque tendría un costo adicional de escritura me parece que el precio vale la pena. Ahora bien, como has mencionado sería genial poderle decir a firebird qué índice debe usar para gestionar adecuadamente el manejo de índices.

Saludos.

  • 0

#14 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 19 febrero 2015 - 12:53

Saludos.

Tal vez puedes forzar que use un plan determinado.
  • 0

#15 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.945 mensajes
  • LocationMéxico

Escrito 19 febrero 2015 - 12:57

Saludos.

Tal vez puedes forzar que use un plan determinado.


Fenomenal amigo... Me parece que vale la pena hacer una prueba sobre esta situación. Voy a aprovechar la info y sacaré las estadísticas de cada consulta para comparar resultados. ¿Qué les parece?
  • 0

#16 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.484 mensajes
  • LocationMallorca

Escrito 20 febrero 2015 - 05:06


Saludos.

Tal vez puedes forzar que use un plan determinado.


Fenomenal amigo... Me parece que vale la pena hacer una prueba sobre esta situación. Voy a aprovechar la info y sacaré las estadísticas de cada consulta para comparar resultados. ¿Qué les parece?


Fantástico, tengo mucha curiosidad para ver el resultado :-)
  • 0

#17 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.945 mensajes
  • LocationMéxico

Escrito 25 febrero 2015 - 10:17

Hola amigos, pues he dado con lo que buscaba. En esta página https://firebird21.w...-en-otra-tabla/ recomiendan el uso de exists en lugar de Joins.

Así que remitiéndonos al ejemplo quedaría:



sql
  1. DELETE
  2.   FROM empleados E
  3. WHERE EXISTS ( SELECT DISTINCT id_empleado
  4.                       FROM empleadosbaja Filtro
  5.                     WHERE E.Id_Empleado = Filtro.Id_Empleado AND
  6.                             Filtro.Pais = Pais)


  • 0

#18 genriquez

genriquez

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 539 mensajes
  • LocationCali, Colombia

Escrito 26 febrero 2015 - 07:30

Muy útil muchas gracias.
  • 0

#19 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.484 mensajes
  • LocationMallorca

Escrito 26 febrero 2015 - 04:42

¿ Porque pones el DISTINCT ?. No veo que aporte nada a la consulta, cuando miras si tu código está dentro del resultado no te importa si está repetido o no en ese conjunto.

Creo que estás añadiendo complejidad a la consulta (con el consiguiente costo en tiempo al ejecutarla) innecesariamente.

A mi esta solución me parece formalmente exactamente igual a las que se plantearon originalmente. No veo la diferencia con :



sql
  1. DELETE
  2. FROM empleados E           
  3. WHERE id_empleado IN ( SELECT id_empleado
  4.                       FROM empleadosbaja Filtro
  5.                       WHERE E.Id_Empleado = Filtro.Id_Empleado AND
  6.                             Filtro.Pais = Pais )


  • 0

#20 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.945 mensajes
  • LocationMéxico

Escrito 26 febrero 2015 - 04:56

Buena observación amigo Marc.

Me traje ese distinct sin querer de la consulta original. En el caso que he publicado no va. :)
Gracias por la corrección.


Edito, para complementar mi respuesta. La consulta original tiene 3 campos llave, por ello requería de un join. esa es la razón de buscar una alternativa.

:) Saludos
  • 0




IP.Board spam blocked by CleanTalk.