Oracle
 sql >> डेटाबेस >  >> RDS >> Oracle

समूह के साथ एसक्यूएल फीफो क्वेरी

विकल्प 1

यह शायद पीएल/एसक्यूएल के लिए एक नौकरी है। डेटा प्रकारों से शुरू होकर आउटपुट तक:

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;

फिर हम INVENTORY_IN . पढ़ने के लिए एक पाइपलाइन फ़ंक्शन को परिभाषित कर सकते हैं और INVENTORY_OUT एक बार में एक पंक्ति को टेबल करें और शेष इन्वेंट्री या आपूर्ति की जाने वाली राशि का कुल योग रखते हुए दोनों को मर्ज करें:

CREATE FUNCTION assign_suppliers_to_customers (
  i_product_id IN INVENTORY_IN.PRODUCT_ID%TYPE
)
RETURN supply_details_tab PIPELINED
IS
  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
  OPEN v_cur_in FOR
    SELECT in_quantity, supplier_id
    FROM   INVENTORY_IN
    WHERE  product_id = i_product_id
    ORDER BY inv_timestamp;

  OPEN v_cur_out FOR
    SELECT out_quantity, customer_id
    FROM   INVENTORY_OUT
    WHERE  product_id = i_product_id
    ORDER BY inv_timestamp;

  LOOP
    IF v_quantity_in IS NULL THEN
      FETCH v_cur_in INTO v_quantity_in, v_supplier_id;
      IF v_cur_in%NOTFOUND THEN
        v_supplier_id := NULL;
      END IF;
    END IF;
    IF v_quantity_out IS NULL THEN
      FETCH v_cur_out INTO v_quantity_out, v_customer_id;
      IF v_cur_out%NOTFOUND THEN
        v_customer_id := NULL;
      END IF;
    END IF;

    EXIT WHEN v_cur_in%NOTFOUND AND 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_quantity_out := NULL;
    ELSE
      PIPE ROW(
        supply_details_obj(
          i_product_id,
          v_quantity_in,
          v_supplier_id,
          v_customer_id
        )
      );
      v_quantity_out := v_quantity_out - v_quantity_in;
      v_quantity_in  := NULL;
    END IF;
  END LOOP;
END;
/

फिर, नमूना डेटा के लिए:

CREATE TABLE INVENTORY_IN ( ID, INV_TIMESTAMP, PRODUCT_ID, IN_QUANTITY, SUPPLIER_ID ) AS
SELECT 0, TIMESTAMP '2021-03-09 00:00:00', 101,  20, 0 FROM DUAL UNION ALL
SELECT 1, TIMESTAMP '2021-03-10 01:00:00', 101, 100, 4 FROM DUAL UNION ALL
SELECT 2, TIMESTAMP '2021-03-11 02:00:00', 101,  50, 3 FROM DUAL UNION ALL
SELECT 3, TIMESTAMP '2021-03-14 01:00:00', 101,  10, 2 FROM DUAL;

CREATE TABLE INVENTORY_OUT ( ID, INV_TIMESTAMP, PRODUCT_ID, OUT_QUANTITY, CUSTOMER_ID ) AS
SELECT 1, TIMESTAMP '2021-03-10 02:00:00', 101, 30, 1 FROM DUAL UNION ALL
SELECT 2, TIMESTAMP '2021-03-11 01:00:00', 101, 40, 2 FROM DUAL UNION ALL
SELECT 3, TIMESTAMP '2021-03-12 01:00:00', 101, 80, 1 FROM DUAL;

क्वेरी:

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

आउटपुट:

विकल्प 2

A (बहुत) जटिल SQL क्वेरी:

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 )
  FROM   inventory_in i
),
out_totals ( ID, 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 ( product_id, inv_timestamp, supplier_id, customer_id, quantity ) AS (
  SELECT 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.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 )
  GROUP BY
         i.product_id,
         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_quantity - COALESCE( s.quantity, 0 )
  FROM   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_id = s.supplier_id )
  ORDER BY i.inv_timestamp
)
SELECT product_id, supplier_id, customer_id, quantity
FROM   (
  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
);

जो, उपरोक्त नमूना डेटा के लिए, आउटपुट करता है:

db<>fiddle यहां



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. ODP.NET 2.111 और ODP.NET 4.112 को एक ही मशीन में एक साथ कैसे स्थापित करें जबकि दोनों एक ही डेटाबेस सर्वर की ओर इशारा करते हैं

  2. आप sqlplus में START का उपयोग करके एक sql फ़ाइल के भीतर PL/SQL ब्लॉक के लिए तर्क कैसे पास करते हैं?

  3. पार्टिशन बाय या मैक्स का उपयोग कैसे करें?

  4. Oracle JDBC DriverManager.getConnection () हैंग हो जाता है

  5. DBA_PROCEDURES दृश्य में प्रक्रिया खोजने में असमर्थ