sql >> Database teknologi >  >> RDS >> Oracle

SQL FIFO-forespørgsel med gruppe efter

Mulighed 1

Dette er sandsynligvis et job til PL/SQL. Starter med de datatyper, der skal udlæses:

CREATE TYPE supply_details_obj AS OBJECT( product_id NUMBER, quantity NUMBER, supplier_id NUMBER, customer_id NUMBER);CREATE TYPE supply_details_tab AS TABLE OF supply_details_obj; 

Så kan vi definere en pipelinet funktion til at læse INVENTORY_IN og INVENTORY_OUT tabeller en række ad gangen og flet de to sammen, mens du beholder en løbende total af den resterende beholdning eller mængde, der skal leveres:

CREATE FUNCTION assign_suppliers_to_customers (i_product_id IN INVENTORY_IN.PRODUCT_ID%TYPE)RETURN supply_details_tab PIPELINEDIS v_supplier_id INVENTORY_IN.SUPPLIER_ID%TYPE; v_customer_id INVENTORY_OUT.CUSTOMER_ID%TYPE; v_quantity_in INVENTORY_IN.IN_QUANTITY%TYPE :=NULL; v_quantity_out INVENTORY_OUT.OUT_QUANTITY%TYPE :=NULL; v_cur_in SYS_REFCURSOR; v_cur_out SYS_REFCURSOR;BEGIN ÅBN v_cur_in FOR SELECT in_quantity, supplier_id FROM INVENTORY_IN WHERE product_id =i_product_id BESTILLE BY inv_timestamp; ÅBN v_cur_out FOR SELECT out_quantity, customer_id FROM INVENTORY_OUT WHERE product_id =i_product_id BESTILLING AF inv_timestamp; LOOP HVIS v_quantity_in ER NULL SÅ FETCH v_cur_in INTO v_quantity_in, v_supplier_id; HVIS v_cur_in%NOTFOUND SÅ v_supplier_id :=NULL; AFSLUT HVIS; AFSLUT HVIS; HVIS v_quantity_out ER NULL SÅ FETCH v_cur_out INTO v_quantity_out, v_customer_id; HVIS v_cur_out%NOTFOUND SÅ v_customer_id :=NULL; AFSLUT HVIS; AFSLUT HVIS; AFSLUT NÅR v_cur_in%NOTFOUND OG v_cur_out%NOTFOUND; IF v_quantity_in> v_quantity_out THEN PIPE ROW( supply_details_obj( i_product_id, v_quantity_out, v_supplier_id, v_customer_id ) ); v_quantity_in :=v_quantity_in - v_quantity_out; v_mængde_ud:=NULL; ELSE PIPE ROW( supply_details_obj( i_product_id, v_quantity_in, v_supplier_id, v_customer_id ) ); v_mængde_ud:=v_mængde_ud - v_mængde_ind; v_quantity_in :=NULL; AFSLUT HVIS; END LOOP;END;/ 

Derefter for eksempeldata:

CREATE TABLE INVENTORY_IN (ID, INV_TIMESTAMP, PRODUCT_ID, IN_QUANTITY, SUPPLIER_ID ) ASSELECT 0, TIMESTAMP '2021-03-09 00:00:00', 101, 20, 0 FRA DUAL UNION SELECT TIMESTAMP 2021-03-10 01:00:00', 101, 100, 4 FRA DUAL UNION ALLSELECT 2, TIMESTAMP '2021-03-11 02:00:00', 101, 50, 3 FRA DUAL UNION ALLSELECT 3, 2021-03-14 01:00:00', 101, 10, 2 FRA DUAL;OPRET TABELINVENTORY_OUT (ID, INV_TIMESTAMP, PRODUCT_ID, OUT_QUANTITY, CUSTOMER_ID ) ASSELECT 1, TIMESTAMP '2020:02'03'2020:02'03' , 101, 30, 1 FRA DUAL UNION ALLSELECT 2, TIMESTAMP '2021-03-11 01:00:00', 101, 40, 2 FRA DUAL UNION ALLSELECT 3, TIMESTAMP '2021-03-12 001:00' , 101, 80, 1 FRA DOBBELT; 

Forespørgslen:

SELECT product_id, supplier_id, customer_id, SUM( quantity ) AS quantityFROM TABLE( assign_suppliers_to_customers( 101 ) )GROUP BY product_id, supplier_id, customer_idORDER BY MIN( inv_timestamp ) 

Udgange:

Mulighed 2

En (meget) kompliceret SQL-forespørgsel:

WITH in_totals ( ID, INV_TIMESTAMP, PRODUCT_ID, IN_QUANTITY, SUPPLIER_ID, TOTAL_QUANTITY ) AS ( SELECT i.*, SUM( in_quantity ) OVER ( PARTITION BY product_id ORDER BY inv_timestamp ) FRA inv_timestamp ) FROM inventory to inventory,_tal INV_TIMESTAMP, PRODUCT_ID, OUT_QUANTITY, CUSTOMER_ID, TOTAL_QUANTITY ) AS ( SELECT o.*, SUM( out_quantity ) OVER ( PARTITION BY product_id ORDER BY inv_timestamp ) FROM inventory_out o),split_totals (v_time_stamp, AS) i.product_id, MIN( COALESCE( LEAST( i.inv_timestamp, o.inv_timestamp ), i.inv_timestamp ) ) AS inv_timestamp, i.supplier_id, o.customer_id, SUM( COALESCE( LEAST( i.total_quantity_o. .out_quantity, o.total_quantity - i.total_quantity + i.in_quantity, i.in_quantity, o.out_quantity ), 0 ) ) FROM in_totals i LEFT OUTER JOIN out_totals o ON ( i.product_id =o.product_id AND i.total_quantity - i.in_quantity <=o.total_quantity AND i.total_quantity>=o.total_quantity - o.out_quantity )_ , i.supplier_id, o.customer_id ORDER BY inv_timestamp),missing_totals ( product_id, inv_timestamp, supplier_id, customer_id, quantity ) AS ( SELECT i.product_id, i.inv_timestamp, i.supplier_id, NULL(-i.in_ALESquantity) kvantitet, 0 ) FRA inventory_in i INNER JOIN ( SELECT product_id, supplier_id, SUM( quantity ) AS quantity FROM split_totals GROUP BY product_id, supplier_id ) s ON ( i.product_id =s.product_id AND i.supplier_liORDER_ s. i.inv_timestamp)SELECT product_id, supplier_id, customer_id, quantityFROM ( SELECT product_id, inv_timestamp, supplier_id, customer_id, quantity FROM split_totals WHERE quantity> 0 UNION ALL SELECT product_id, inv_timestamp, supplier_id, customer_id, quantity FROM missing_totals WHERE quantity> 0 ORDER BY inv_timestamp);

Hvilket, for eksempeldataene ovenfor, udsender:

db<>fiddle her



  1. MySQL 5.6 Full Text Search Problem ved søgning efter ordet i PHP

  2. Dato casting i oracle

  3. Hvordan opretter jeg en indlejret funktion i PL/pgSQL?

  4. Ruby PostgreSQL tutorials