Aquí tienes un ejemplo muy sencillo para comprender su uso:
- ¡Todo es rápido y no hay necesidad de guardar datos en otra tabla!
Si utiliza
Firebird, podría crear un "Procedimiento almacenado" parametrizado para poder cambiar los nombres de las tablas y los campos y adaptarlos a diferentes años...
Código SQL
[-]
SET TERM ^ ;
CREATE OR ALTER PROCEDURE GetTableDataCombined (
ATableNameA VARCHAR(31),
ATableNameB VARCHAR(31),
AFieldTableName VARCHAR(31),
AFieldInputDate VARCHAR(31),
AFieldIDRecord VARCHAR(31),
AFieldValue VARCHAR(31),
AStartDate DATE,
AEndDate DATE
)
RETURNS (
OutSourceTable VARCHAR(31),
OutTableName VARCHAR(100),
OutInputDate DATE,
OutIDRecord INT64,
OutValue NUMERIC(18,4),
OutErrorMessage VARCHAR(255)
)
AS
DECLARE VARIABLE VSqlStatement VARCHAR(4000);
BEGIN
OutErrorMessage = '';
-- Crea una única consulta uniendo las dos tablas mediante UNION ALL.
VSqlStatement = 'SELECT ''' || :ATableNameA || ''', ' || :AFieldTableName || ', ' || :AFieldInputDate || ', ' || :AFieldIDRecord || ', ' || :AFieldValue || ' ' ||
'FROM ' || :ATableNameA || ' ' ||
'WHERE ' || :AFieldInputDate || ' BETWEEN :PStart AND :PEnd ' ||
'UNION ALL ' ||
'SELECT ''' || :ATableNameB || ''', ' || :AFieldTableName || ', ' || :AFieldInputDate || ', ' || :AFieldIDRecord || ', ' || :AFieldValue || ' ' ||
'FROM ' || :ATableNameB || ' ' ||
'WHERE ' || :AFieldInputDate || ' BETWEEN :PStart AND :PEnd';
-- El bucle FOR ejecuta la instrucción unificada de una sola vez.
FOR EXECUTE STATEMENT :VSqlStatement (PStart := :AStartDate, PEnd := :AEndDate)
INTO :OutSourceTable, :OutTableName, :OutInputDate, :OutIDRecord, :OutValue
DO
BEGIN
SUSPEND;
End
-- Manejo estructurado de excepciones
WHEN ANY DO
BEGIN
OutSourceTable = 'ERROR';
OutTableName = '';
OutInputDate = NULL;
OutIDRecord = 0;
OutValue = 0;
OutErrorMessage = 'Error al ejecutar la consulta unificada con UNION ALL.';
SUSPEND;
END
END^
SET TERM ; ^
Ejemplo de uso en Delphi, utilizando TFDQuery o cualquier consulta similar.
Código Delphi
[-]
Procedure TFormMain.FetchDataForComparison;
Begin
FDQueryCompare.Close;
FDQueryCompare.SQL.Text := 'SELECT * FROM GetTableDataForCompare(:TabA, :TabB, :FldTabName, :FldDate, :FldID, :FldVal,
tStart,
tEnd)';
FDQueryCompare.ParamByName('TabA').AsString := 'TableA';
FDQueryCompare.ParamByName('TabB').AsString := 'TableB';
FDQueryCompare.ParamByName('FldTabName').AsString := 'TableName';
FDQueryCompare.ParamByName('FldDate').AsString := 'InputDate';
FDQueryCompare.ParamByName('FldID').AsString := 'IDRecord';
FDQueryCompare.ParamByName('FldVal').AsString := 'Value';
FDQueryCompare.ParamByName('DtStart').AsDateTime := DateTimePickerStart.Date;
FDQueryCompare.ParamByName('DtEnd').AsDateTime := DateTimePickerEnd.Date;
FDQueryCompare.Open;
If Not FDQueryCompare.FieldByName('OutErrorMessage').AsString.IsEmpty Then
Begin
FDQueryCompare.Close;
ShowMessage('ERROR: ' + FDQueryCompare.FieldByName('OutErrorMessage').AsString);
Exit;
End;
End;