Dividir consultas
Hay ocasiones en las que no se puede, o no sabemos, hacer una consulta.
Tenemos clara la consulta, creemos que va a funcionar, pero no es así y nos vemos obligados a realizar una consulta ‘auxiliar’ que puesta en una nueva consulta nos da los resultados que esperamos.
A mi me suele pasar, sobre todo, con las consultas de totales.
Supongamos que tenemos la siguiente tabla:
Movimientos |
FechaMovimiento | CodigoCliente | Referencia | Monto |
12/06/2009 | 5223 | VENTA | 1000 |
18/06/2009 | 5223 | PAGO | -150 |
24/06/2009 | 5223 | PAGO | -80 |
28/06/2009 | 5223 | PAGO | -120 |
30/06/2009 | 5223 | PAGO | -100 |
12/06/2009 | 8888 | VENTA | 1000 |
18/06/2009 | 8888 | PAGO | -10 |
24/06/2009 | 8888 | PAGO | -90 |
28/06/2009 | 8888 | PAGO | -120 |
30/06/2009 | 8888 | PAGO | -110 |
02/07/2009 | 8888 | PAGO | -80 |
12/07/2009 | 8888 | PAGO | -100 |
Con el campo FechaMovimiento de tipo fecha, el campo Monto de tipo numérico, y los otros dos tipo texto.
Supongamos que quiero obtener los registros del último pago de cada cliente, es decir:
UltimosPagos |
CodigoCliente | LaFecha | Referencia | Monto |
5223 | 30/06/2009 | PAGO | -100 |
8888 | 12/07/2009 | PAGO | -100 |
Pensando en una consulta de totales monto la siguiente consulta:

SELECT Movimientos.CodigoCliente, Max(Movimientos.FechaMovimiento) AS LaFecha
FROM Movimientos
WHERE (((Movimientos.Referencia)="pago"))
GROUP BY Movimientos.CodigoCliente;
Que ya me devuelve la ultima fecha de pago de cada cliente:
Auxiliar |
CodigoCliente | LaFecha |
5223 | 30/06/2009 |
8888 | 12/07/2009 |
Ahora pienso que con añadir los campos referencia y Monto tendré mi problema resuelto pero NO soy capaz de poner esos campos en la consulta de totales.
Llegados a este punto decido guardar la consulta anterior como Auxiliar y hacer una nueva consulta como la siguiente:

SELECT Auxiliar.CodigoCliente, Auxiliar.LaFecha, movimientos.Referencia, movimientos.Monto
FROM Auxiliar INNER JOIN movimientos ON (Auxiliar.CodigoCliente = movimientos.CodigoCliente) AND (Auxiliar.LaFecha = movimientos.FechaMovimiento);
Que me devuelve los resultados esperados.
Consultas anidadas
Hasta aquí todo bien, pero si la Auxiliar solo la usamos para hacer la consulta definitiva, podemos poner la SQL de Auxiliar dentro de la consulta final, eliminar la consulta Auxiliar y quedarnos solo con una consulta.
Veamos como ponemos la SQL de una consulta dentro de otra.
Para que la explicación sea más sencilla supongamos la siguiente consulta
SELECT Tabla1.Campo1, Tabla1.Campo2
FROM Tabla1;
que llamo Auxiliar
Supongamos que la consulta Auxiliar solo la uso para la siguiente consulta
SELECT Auxiliar.Campo1
FROM Auxiliar;
En este caso, la segunda consulta podemos modificarla como sigue
SELECT Auxiliar.Campo1
FROM (SELECT Tabla1.Campo1, Tabla1.Campo2
FROM Tabla1) as Auxiliar;
y podemos borrar la consulta Auxiliar.
Observad que lo que hemos hecho ha sido poner en el FROM y delante del nombre de la consulta
(La SQL de la consulta auxiliar sin el ; final) AS
Paréntesis, la SQL de la consulta auxiliar sin el ; final, paréntesis, y AS
Volviendo a nuestras consultas iniciales teníamos
Auxiliar
SELECT Movimientos.CodigoCliente, Max(Movimientos.FechaMovimiento) AS LaFecha
FROM Movimientos
WHERE (((Movimientos.Referencia)="pago"))
GROUP BY Movimientos.CodigoCliente;
Consulta UltimosPagosConAuxiliar:
SELECT Auxiliar.CodigoCliente, Auxiliar.LaFecha, movimientos.Referencia, movimientos.Monto
FROM Auxiliar INNER JOIN movimientos ON (Auxiliar.CodigoCliente = movimientos.CodigoCliente) AND (Auxiliar.LaFecha = movimientos.FechaMovimiento);
Siguiendo las indicaciones anteriores podemos tener una única consulta que he llamado UltimosPagosDirecta:
SELECT [Auxiliar].CodigoCliente, [Auxiliar].LaFecha, movimientos.Referencia, movimientos.Monto
FROM (SELECT Movimientos.CodigoCliente, Max(Movimientos.FechaMovimiento) AS LaFecha
FROM Movimientos
WHERE (((Movimientos.Referencia)="pago"))
GROUP BY Movimientos.CodigoCliente) as Auxiliar INNER JOIN movimientos ON ([Auxiliar].LaFecha=movimientos.FechaMovimiento) AND ([Auxiliar].CodigoCliente=movimientos.CodigoCliente);
Aviso importante
Si tenemos una consulta como la que he indicado
SELECT Auxiliar.Campo1
FROM (SELECT Tabla1.Campo1, Tabla1.Campo2
FROM Tabla1) as Auxiliar;
al guardarla, Access la transforma dejándola como sigue
SELECT Auxiliar.Campo1
FROM [SELECT Tabla1.Campo1, Tabla1.Campo2
FROM Tabla1]. AS Auxiliar;
Access cambia los corchetes por paréntesis y añade un punto.
Con esta sintaxis la consulta sigue funcionando bien pero en ocasiones, si posteamos esta SQL con corchetes y punto y alguien la copia en una nueva consulta NO FUNCIONA.
¿Qué hacer si nos proponen una consulta con corchetes y punto y no funciona?
Cambiar los corchetes por paréntesis y quitar el punto.