PDA

Ver la Versión Completa : Reutilizar resultado de SQL en SQL


javiermorales
05-09-2003, 10:30:42
buenos Días, una pregunta simple. Cuando se realiza una SQL en un componente ADOQuery, ¿es posible reutilizar esa consulta dentro de otra ADOQuery, sin necesidad de crear una tabla física en la BD (aunque sea en tiempo de ejecución)?.

Me explico:

1.- Realizo un ADOQuery:

.....
ADOQuery1.SQL.Add('select * from tabla1');
ADOQuery1.Active := true;
.....

2.- ¿Puedo hacer otra SQL, donde utilice la ADOQuery1 como una tabla más?.

......
ADOQuery2.SQL.Add('select * from tabla1 a,ADOQuery1 b'+
' where a.dato1= b.dato2')
......


Gracias. Un saludo.

delphi.com.ar
05-09-2003, 15:51:42
Query.Sql.Text := 'SELECT * FROM EMPLEADOS';
Query.Open;
....
Query.Close;
Query.Sql.Text := 'SELECT * FROM EMPLEADOS, EMPRESA WHERE...';
Query.Open;

¿Eso es lo que preguntas?

javiermorales
05-09-2003, 17:58:39
Gracias por contestar delphi.com.ar, en realidad la pregunta se dirige mas a la manera de utilizar los resultados de una consulta SQL, como si fuese una tabla más. Algo similar a los cursores de Visual Foxpro.

Es decir tu realizas una consulta SQL que te devuelve unos resultados concretos y esos resultados se encuentran disponibles aunque se modifiquen los datos de origen ya que tú los tienes en memoria. Esos resultados pueden servirte para múltiples utilidades y entre ellas lo que búsco es utilizarlos dentro de otra consulta SQL. A grandes rasgos, ¿se podría realizar una SQL sobre esos resultados?.

En tu ejemplo, ¿podría hacer?:

Query1.Sql.Text := 'SELECT * FROM EMPLEADOS';
Query1.Open;
Query2.Sql.Text := 'SELECT * FROM Query1, EMPRESA WHERE...';
Query2.Open;


Gracias. Un saludo.

delphi.com.ar
05-09-2003, 18:09:06
Pero si hablas de SQL, es lo mismo... Digamos que lo único que haces es agregar una tabla y/o mas condiciones... No estas alterando el resultado. Tus resultados estan directamente relacionados con el SQL.

Saludos!

javiermorales
05-09-2003, 18:39:18
El problema me ha surgido, cuando debo actualizar los datos de una tabla basándome en la propia tabla. Es decir, tengo una tabla con los siguientes datos:

Codigo Texto Valor1 Valor2
1 prueba1 32 12
2 prueba2 31 11
1 10
3 prueba3 22 19
2 prueba6 30 15
1 17


Dados estos valores yo necesito actualizar todos los códigos que no tienen texto o valor con los datos de los que sí lo tienen y poseen el mismo código. Como puede verse también existen elementos con el mismo código, pero con valores diferentes.

Para solucionarlo, he utilizado la siguiente sentencia:
1.- Obtengo los códigos que no utilizaré en la actualización

(SQL1)
SELECT Codigo, Count(Codigo)
FROM Tabla
WHERE Valor1 Is Not Null
GROUP BY Codigo
HAVING Count(Codigo)>1


2.- Obtengo los datos para actualizar

(SQL2)
SELECT Codigo, Texto, Valor1
FROM Tabla LEFT JOIN SQL1 ON Tabla.Codigo = SQL1.Codigo
WHERE SQL1.Codigo Is Null


3.- Actualizo los datos de tabla con los de SQL2

Si todo esto lo realizo sin la ayuda de una tabla auxiliar, no podría actualizar los datos de tabla1, ya que estaría utilizando los propios datos de tabla1 para decidir cual debo actualizar. Es decir el típico problema de consulta no actualizable en el UPDATE.

Por esto es por lo que deseo utilizar los resultados que tengo en memoria como una tabla independiente.

Gracias. Un saludo.

javiermorales
05-09-2003, 21:33:43
Hola de nuevo, el tipo de consultas que quiero realizar y que no se me ocurre como hacer sin la creación de tablas en la BD son como esta:


UPDATE TMPPAR AS a SET a.TMPPAR_TXT = (select distinct b.TMPPAR_TXT from TMPPAR AS b where a.TMPPAR_COD=b.TMPPAR_COD and b.TMPPAR_TXT is not null and b.TMPPAR_TXT<>'')
WHERE a.TMPPAR_TXT is null or a.TMPPAR_TXT='';


El motor no me deja hacerlo, porque como es lógico actualizo la tabla con los datos de la misma tabla.

Espero vuestra ayuda. Un saludo

guillotmarc
05-09-2003, 23:11:28
Hola.

Eso es una subconsultas, y normalmente todos los servidores SQL las aceptan (excepto MySQL).

¿ Que motor utilizas ?

Saludos.

javiermorales
06-09-2003, 10:55:23
Hola guillotmarc, utilizo Access 2000. En efecto son subconsultas y se pueden utilizar sin ningún problema. El problema proviene de utilizar como subconsulta la propia tabla que estas intentando actualizar con el UPDATE.


UPDATE A as 1 SET 1.dat=(select 2.dat from A as 2)


Suponiendo lo mas básico, que en esa tabla solo tienes un registro, tambien fallaría.

En este tipo de casos, yo en otro motores utilizaba tablas temporales, cursores o estrategias similares, pero en Delphi, ¿me preguntaba si el resultado de una consulta podía utilizarse como un cursor y utilizarla su resultado dentro de otra SQL?.

Gracias. Un saludo.

guillotmarc
06-09-2003, 18:50:47
Hola.

Parece ser un problema del Access 2000. Lo he probado, y simplemente no acepta subconsultas en el UPDATE (sea la subconsulta la propia tabla a modificar, o no).

Si solo fuera un problema de que la tabla es la misma en la subconsulta y en el UPDATE, bastaría con crear una vista igual a la tabla, y hacer la subconsulta sobre la vista. Pero lo he probado, y parece ser que Access no permite ningún tipo de subconsulta en el UPDATE (ni sobre la misma tabla, una vista, u otra tabla cualquiera).

El problema de utilizar cursores SQL, es que se utilizan desde procedimientos almacenados (donde se pueden indicar varias instrucciones SQL : para definir el cursor, recorrerlo, actualizar la tabla, ...), pero Access no tiene un lenguaje de procedimientos almacenados.

Así parece ser que tendrás que hacerlo todo en Delphi. Un cursor en Delphi, es un Dataset abierto con un TADOQuery, lo abres y lo puedes recorrer y modificar.

Simplemente pón un TQuery para recorrer la tabla, y otro TQuery para averiguar el valor buscado. Recorres el primer Query y para cada registro, cierras y vuelves a abrir el segundo Query, averiguando el valor que necesitas para modificar el registro actual en el primer Query.

Más o menos :


ADOQuery1.Open
while not ADOQuery1.Eof do begin
ADOQuery2.Params.ParamValues['Codigo'] := ADOQuery1.FieldValues['Codigo'];
ADOQuery2.Open;
ADOQuery1.Edit;
ADOQuery1.FieldValues['Campo'] := ADOQuery2.FieldValues['Resultado'];
ADOQuery1.Post;
ADOQuery2.Close;
ADOQuery1.Next;
end;


Espero que sea esto lo que buscas.

Saludos.

javiermorales
06-09-2003, 19:11:32
Gracias por contestar guillotmarc, dadas las limitaciones de Access 2000, lo realizaré como indicas.

Gracias a todos por vuestras contestaciones.

Un saludo.