Tengo bastante experiencia con las funciones analíticas de Oracle, pero esta me ha dejado perplejo. Me patearé a mí mismo si hay una solución obvia :)Interesante desafío de consulta analítica de Oracle
Tengo una tabla, JOURNAL, que registra Inserciones, Actualizaciones y Eliminaciones en otra tabla.
La tabla para la que es un diario es BOND_PAYMENTS, que representa enlaces entre PAYMENTS y BONDS; almacena la cantidad de dinero (AMOUNT) que se asignó a un bono en particular (identificado por BOND_NUMBER) a partir de un pago en particular (identificado por PAYMENT_ID). Además, registra a qué aspecto del enlace se asignó (BOP_DOMAIN) que podría ser 'BON', 'PET' o algún otro código. La tabla BOND_PAYMENTS tiene una clave sustituta (BOP_ID).
Por lo tanto, mi tabla de diario generalmente tendrá 1 o más registros para cada BOP_ID - en primer lugar, un INSert, seguido quizás por algunos UPDates, seguido quizás por un DELete.
Aquí está la tabla REVISTA:
CREATE TABLE JOURNAL
(JN_DATE_TIME DATE NOT NULL,
JN_OPERATION VARCHAR2(3) NOT NULL,
BOP_ID NUMBER(9) NOT NULL,
PAYMENT_ID NUMBER(9) NOT NULL,
BOND_NUMBER VARCHAR2(20) NOT NULL,
BOP_DOMAIN VARCHAR2(10) NOT NULL,
AMOUNT NUMBER(14,2) NOT NULL
);
Aquí es un poco de datos de ejemplo:
INSERT INTO JOURNAL VALUES (TO_DATE('01/01/2010','DD/MM/YYYY'),'INS',1242043,1003700,'9995/10','BON',1800);
INSERT INTO JOURNAL VALUES (TO_DATE('03/01/2010','DD/MM/YYYY'),'INS',1242046,1003700,'9998/10','BON',1700);
INSERT INTO JOURNAL VALUES (TO_DATE('04/01/2010','DD/MM/YYYY'),'INS',1242048,1003700,'9999/10','BON',1800);
INSERT INTO JOURNAL VALUES (TO_DATE('05/01/2010','DD/MM/YYYY'),'INS',1242052,1003700,'10003/10','BON',1600);
INSERT INTO JOURNAL VALUES (TO_DATE('08/01/2010','DD/MM/YYYY'),'INS',1242058,1003700,'9998/10','BON',100);
INSERT INTO JOURNAL VALUES (TO_DATE('09/01/2010','DD/MM/YYYY'),'UPD',1242058,1003700,'9998/10','PET',100);
INSERT INTO JOURNAL VALUES (TO_DATE('01/01/2010','DD/MM/YYYY'),'INS',2242043,1003701,'8995/10','BON',1800);
INSERT INTO JOURNAL VALUES (TO_DATE('02/01/2010','DD/MM/YYYY'),'INS',2242046,1003701,'8998/10','BON',1700);
INSERT INTO JOURNAL VALUES (TO_DATE('03/01/2010','DD/MM/YYYY'),'INS',2242048,1003701,'8999/10','BON',1800);
INSERT INTO JOURNAL VALUES (TO_DATE('04/01/2010','DD/MM/YYYY'),'INS',2242058,1003701,'8998/10','BON',100);
INSERT INTO JOURNAL VALUES (TO_DATE('05/01/2010','DD/MM/YYYY'),'UPD',2242046,1003701,'8998/10','BON',1500);
INSERT INTO JOURNAL VALUES (TO_DATE('06/01/2010','DD/MM/YYYY'),'INS',2242052,1003701,'9003/10','BON',1600);
INSERT INTO JOURNAL VALUES (TO_DATE('07/01/2010','DD/MM/YYYY'),'UPD',2242058,1003701,'8998/10','PET',200);
Ahora, tengo que extraer un conjunto completo de datos de esta tabla revista pero en un poco diferente formato. El requisito principal es que no queremos que la tabla de diario registre BOP_DOMAIN nunca más, simplemente no es obligatorio.
Necesito generar un historial del monto total para cada registro de BOND_PAYMENT. No puedo usar la tabla BOND_PAYMENT en sí porque solo muestra el estado más reciente de cada registro. Necesito extraer esta información de la revista.
No puedo tomar simplemente un SUM(amount) over(partition by payment_id, bond_number)
porque un BOP_ID individual puede actualizarse varias veces; por lo que en cualquier momento en el tiempo solo se debe usar la última cantidad registrada para ese BOP_ID.
Teniendo en cuenta los datos de las muestras anteriores, aquí es una ilustración lo que cabe esperar para producir:
SELECT jn_date_time,
jn_operation,
bop_id,
payment_id,
bond_number,
bop_domain,
amount,
? as running_total
FROM JOURNAL
ORDER BY jn_date_time;
Aquí he reproducido a la izquierda los datos de la muestra, para los dos pagos de muestras . A la derecha, tengo "Running Total", que es el resultado esperado. Junto a él (en rojo) está la lógica de cómo calculó el total acumulado de cada fila.
El "Total acumulado" es una instantánea, en el momento de la entrada del diario, del importe total para esa combinación de PAYMENT_ID y BOND_NUMBER. Recuerde, un BOP_ID particular puede actualizarse varias veces; el monto total debe considerar solo el registro más reciente para ese BOP_ID.
Cualquier solución que funcione será aceptable, pero sospecho que una función analítica (o combinación de funciones analíticas) será la mejor manera de resolver esto.
muy agradable :) veo lo que está haciendo allí. En primer lugar, calcular la cantidad de la cantidad cambiado desde la entrada pertinente anterior (a través de LAG), entonces es sólo una cuestión de calcular una suma continua a través de los deltas. –
sus suposiciones son correctas. –