PDA

Ver la Versión Completa : Sentencia SQL simultanea en dos tablas


netcom
04-05-2017, 16:08:26
Buenas chicos,

La siquiente pregunta esta relacionada con SQl en Delphi XE2. La base de datos con la que trabajo es de ACCES, con TADO.

Tengo la siguiente consulta que funciona a la perfección:
With Datamodule1.ADOQuery_consultasFlujo Do
Begin
Close;
SQL.Clear;
SQL.Add('SELECT * FROM Entradas_Salidas_ECS WHERE tipo_de_entrada =:condicion1 ');
SQL.Add('and tipo_de_salida =:condicion2 and nombre =:condicion3 ');
SQL.Add('and Fecha_salida BETWEEN :condicion4 and :condicion5 ');
SQL.Add('and Fecha_recepcion BETWEEN :condicion6 and :condicion7');
Parameters.ParamByName('condicion1').Value:=RG_Entradas.Items.strings[RG_Entradas.ItemIndex];
Parameters.ParamByName('condicion2').Value:=RG_Salidas.Items.strings[RG_Salidas.ItemIndex];
Parameters.ParamByName('condicion3').Value:=E_Empresa.text;
Parameters.ParamByName('condicion4').Value:=E_Entrada_Inicio.Text;
Parameters.ParamByName('condicion5').Value:=E_Entrada_Fin.Text;
Parameters.ParamByName('condicion6').Value:=E_Salida_Inicio.Text;
Parameters.ParamByName('condicion7').Value:=E_Salida_Fin.Text;
Open;
End;

Ahora querría que la consulta se hiciera de forma simultánea en dos tablas, la tabla Entradas_Salidas_ECS y la tabla Entradas_Salidas_BEA, (ambas tablas tienen la misma estructura). He probado algo así:

With Datamodule1.ADOQuery_consultasFlujo Do
Begin
Close;
SQL.Clear;
SQL.Add('SELECT * FROM Entradas_Salidas_ECS, Entradas_Salidas_BEA WHERE tipo_de_entrada =:condicion1 ');
SQL.Add('and tipo_de_salida =:condicion2 and nombre =:condicion3 ');
SQL.Add('and Fecha_salida BETWEEN :condicion4 and :condicion5 ');
SQL.Add('and Fecha_recepcion BETWEEN :condicion6 and :condicion7');
Parameters.ParamByName('condicion1').Value:=RG_Entradas.Items.strings[RG_Entradas.ItemIndex];
Parameters.ParamByName('condicion2').Value:=RG_Salidas.Items.strings[RG_Salidas.ItemIndex];
Parameters.ParamByName('condicion3').Value:=E_Empresa.text;
Parameters.ParamByName('condicion4').Value:=E_Entrada_Inicio.Text;
Parameters.ParamByName('condicion5').Value:=E_Entrada_Fin.Text;
Parameters.ParamByName('condicion6').Value:=E_Salida_Inicio.Text;
Parameters.ParamByName('condicion7').Value:=E_Salida_Fin.Text;
Open;
End;

Pero no funciona, al ejecutar la sentencia me salta el siguiente error: "Objeto Parameter mal definido. Se proporcionó información incompleta o incoherente".
Buscando por el foro he visto los comandos JOIN ON, LEFT JOIN pero me salta el mismo error.

Tenéis idea de como debería ser la estructura correcta de la sentencia para que el SQL me devolviera los resultados encontrados en ambas tablas?

Muchas Gracias!

mamcx
04-05-2017, 16:57:39
Si no sabes que es un JOIN deberias darte un estudio sobre SQL. SQL es un lenguaje realmente muy simple, aunque tiene unas cuantas cosas un poco raras (como el orden estricto de los operadores). Con unas pocas horas de estudio y analisis podras operar de forma eficiente por años.

El error es sobre un parametro mal especificado. Tendras que mirar uno a uno cual es.

Ademas:

condicion1, condicion2 son malos nombres para los parametros. Usa nombres descriptivos. Y es mejor que primero hagas pruebas de los SQL de forma directa en el motor y luego los pases a Delphi.

movorack
04-05-2017, 17:21:56
Como te dice Mario, El error está en los parámetros.
Al asignar el valor de cada uno de ellos, Determina el tipo de dato para evitar errores.


With Datamodule1.ADOQuery_consultasFlujo Do
Begin
Close;
SQL.Clear;
SQL.Add(' SELECT * ');
SQL.Add(' FROM Entradas_Salidas_ECS, Entradas_Salidas_BEA ');
SQL.Add(' WHERE tipo_de_entrada = :tipo_de_entrada ');
SQL.Add(' and tipo_de_salida = :tipo_de_salida ');
SQL.Add(' and nombre = :nombre ');
SQL.Add(' and Fecha_salida BETWEEN :Fecha_salidI and :Fecha_salidF ');
SQL.Add(' and Fecha_recepcion BETWEEN :Fecha_recepcioI and :Fecha_recepcioF');
Parameters.ParamByName('tipo_de_entrada').AsString := RG_Entradas.Items.strings[RG_Entradas.ItemIndex];
Parameters.ParamByName('tipo_de_salida').AsString := RG_Salidas.Items.strings[RG_Salidas.ItemIndex];
Parameters.ParamByName('nombre').AsString := E_Empresa.text;
Parameters.ParamByName('Fecha_salidI').AsDateTime := E_Entrada_Inicio.Text;
Parameters.ParamByName('Fecha_salidF').AsDateTime := E_Entrada_Fin.Text;
Parameters.ParamByName('Fecha_recepcioI').AsDateTime := E_Salida_Inicio.Text;
Parameters.ParamByName('Fecha_recepcioF').AsDateTime := E_Salida_Fin.Text;
Open;
End;


Y de igual manera, dale una leída a las bases de SQL (https://www.w3schools.com/sql/DEfaULT.asP) porque si quieres hacer la consulta en esas dos tablas, necesitas o hacer un join o una union

netcom
04-05-2017, 19:33:30
Muchas gracias por los comentarios.

Dudo que los parametros esten mal definidos, cuando solo hago mencion a una tabla funciona a las mil maravillas, a la que meto la segunda tabla es cuando da error. Creo que delphi interpreta a la segunda tabla como si fuera un parametro sin definir...

A ver que en ecuentro en las bases de sql

roman
04-05-2017, 20:33:29
Esa consulta va a traer muchos resultados, específicamente N*M si N es el número de registros en una tabla y M el número de registros en la otra tabla y juraría que eso no es lo que quieres. Ya movorack lo apuntó: necesitas hacer un UNION, no un JOIN.

Toma en cuenta además que, aún suponiendo que lo que quieres es ese JOIN, la consulta va a fallar porque al tener la misma estructura ambas tablas, las columnas -supongo- se llaman igual y el motor debe generar un error de ambigüedad al referirte a las columnas sin anteponer el nombre de la tabla.

LineComment Saludos

Errorware
22-05-2017, 20:50:16
Si entendi bien lo que quieres hacer la sentencia se debiera ver algo como (con sample data, claramente):


CREATE TABLE #EntradasSalidasECS (
EntradaSalidaECSId int,
TipoEntrada varchar(20),
TipoSalida varchar(20),
FechaEntrada date,
FechaSalida date)

CREATE TABLE #EntradasSalidasBEA (
EntradaSalidaBEAId int,
TipoEntrada varchar(20),
TipoSalida varchar(20),
FechaEntrada date,
FechaSalida date)

INSERT INTO #EntradasSalidasECS VALUES
(1, 'E1', 'S2', '2017-01-01', '2017-01-02'),
(2, 'E1', 'S2', '2017-02-01', '2017-02-02'),
(3, 'E2', 'S2', '2017-03-01', '2017-03-02'),
(4, 'E3', 'S1', '2017-04-01', '2017-04-02')

INSERT INTO #EntradasSalidasBEA VALUES
(1, 'E2', 'S1', '2017-05-01', '2017-05-02'),
(2, 'E1', 'S1', '2017-06-01', '2017-06-02'),
(3, 'E2', 'S3', '2017-07-01', '2017-07-02'),
(4, 'E2', 'S3', '2017-08-01', '2017-08-02')

SELECT
*
FROM (
SELECT * FROM #EntradasSalidasECS
UNION ALL
SELECT * FROM #EntradasSalidasBEA) t1
WHERE
t1.TipoEntrada = @TipoEntrada AND
t1.TipoSalida = @TipoSalida AND
t1.FechaSalida BETWEEN @FechaSalidaDesde AND @FechaSalidaHasta
t1.FechaEntrada BETWEEN @FechaEntradaDesde AND @FechaEntradaHasta



Pero claramente si las dos tablas son tan similares hay un error de diseno... La solucion real seria fusionar las dos tablas y agregar un campo de 'Tipo de Movimiento' que haga referencia a una nueva tabla donde almacenas ECS, BEA... (para seguir con el ejemplo).

Saludos.

gatosoft
24-05-2017, 15:41:31
De acuerdo con todos.

Primero:parece que estas haciendo una consulta cuyo resultado no es el que esperas, y Segundo: estas ASUMIENDO y JUZGANDO que el error es en la forma como delphi interpreta la consulta, cuando el error es claro, es de parámetros.

Primero, la consulta que estas haciendo es un inner Join impliscito

Select *
from tabla1, tabla2

el cual requiere que definas un criterio por el cual las tablas harán Join

Select *
from tabla1, tabla2
where llaveTabla1 = llaveTabla2
..otras condiciones..


Por otro lado, parece evidente que tus tablas tienen nombres similares de campos, por lo que es necesario que te apoyes con alias para evitar errores de ambiguedades:

Select T1.*, T2.*
from tabla1 T1, tabla2 T2
where T1.llave = T2.llave
..otras condiciones..


Eso a grosso modo,

Segundo, cuando defines un parametro dentro de una cadena de texto (Select * from Tabla where Campo =:Parametro), el compilador intentará determinar el tipo de campo que le estas pasando al momento de la asignación del valor del parametro,

Asi si dices:

XXXX.Parambyname('Hora').Values:= '2 de la tarde';

El compilador intentará convertir el valor asignado al valor que considera.. en el caso anterior será a texto, y no a hora. Por eso es mejor forzar el cast como te indicó movorak en su post.

Normalmente son los campos de fecha y hora los que presentan mas problemas debido a los diversos formatos que éstos pueden aceptar.

intenta hacer una prueba de tu SQL, aislando parametros, algo asi:

SELECT *
FROM Entradas_Salidas_ECS, Entradas_Salidas_BEA
WHERE tipo_de_entrada = 'E1'
and tipo_de_salida = 'S1'
and nombre = 'UnNombre'
and Fecha_salida BETWEEN '2017-01-01' and '2017-01-01'
and Fecha_recepcion BETWEEN :Fecha_recepcioI and :Fecha_recepcioF

Asi, vas probando de uno en uno o de dos en dos, para verificar que cada parametro esta siendo bien interpretado...


bye