Home > Mobile >  SQL Query to fetch the latest payment method and invoice date
SQL Query to fetch the latest payment method and invoice date

Time:01-07

There are four tables

First - Customer Second - Invoice Third - Supplier Fourth - Supplier_Remit

Tables details are mentioned below

Customer_id Customer_Account_number Customer_Status Supplier_id Supplier_Remit_id
1 1501 Active 11 111
2 1502 Inactive 12 112
3 1503 Active 13 113
4 1504 Active 14 114
5 1505 Inactive 15 115
Invoice_Date Invoice_Amount Invoice_Number Payment Method Customer_id
01/01/2023 100 1000001 Cash 1
12/01/2022 150 1000002 Credit Card 1
11/09/2022 200 1000003 Credit Card 1
12/09/2022 300 1000004 Cash 2
04/15/2022 1000 1000005 Cash 2
04/15/2022 1000 1000006 Credit Card 3
10/31/2022 250 1000007 Cash 4
10/25/2022 250 1000008 Cash 4
09/20/2022 130 1000009 Credit Card 5
05/20/2022 120 10000010 Credit Card 5
Supplier_Name Supplier_id
ABC 11
ACCC 12
ADEF 13
AJKL 14
AFLR 15
City Country Supplier_Remit_id Supplier_id
Boston US 111 11
Oak US 112 12
Albany US 113 13
Madison US 114 14
Los Ang US 115 15

I need help in finding the most recent payment method, most recent invoice amount, no of count of invoices missing for current year (2023) and no of count of invoices missing for previous year(2022)

I have written query to find first few columns but unable to write further to get the above mentioned details

select c.customer_id,c.customer_account_number,c.customer_status,sr.country,max(i.invoice_date) as Latest receieved_Invoice_date
from 
customer c,
invoice i,
supplier s,
supplier_Remit sr
where 
c.customer_status='Active' and
sr.supplier_id=s.supplier_id and
c.supplier_remit_id=sr.supplier_remit_id and
c.customer_id=i.customer_id
group by
c.customer_id,c.customer_account_number,c.customer_status,sr.country;

My expected output would be as below

Customer_id Cust_Acct_Num Cust_Status Country Last_Inv_Rec_Date
1 1501 Active US 01/01/2023
3 1503 Active US 04/15/2022
4 1504 Active US 10/31/2022
Latest_Paym_Method Lastest_Inv_Amt Count of Missing Inv for Curr Yr
Cash 100 0
Credit card 1000 1
Cash 250 1
Count of Missing Invoices for Prev Year
10
11
11

CodePudding user response:

You can use MAX(...) KEEP (DENSE_RANK LAST ORDER BY invoice_date) to get values for the latest invoice and conditional aggregation to count the number of months where there are invoices and then subtract from the total number of months to find the missing invoices:

SELECT c.Customer_id,
       c.Customer_Account_number,
       c.Customer_Status,
       r.country,
       i.last_invoice_date,
       i.latest_payment_method,
       i.latest_invoice_amount,
       EXTRACT(MONTH FROM SYSDATE) - COALESCE(i.missing_invoices_this_year, 0)
         AS missing_invoices_this_year,
       12 - COALESCE(i.missing_invoices_last_year, 0)
         AS missing_invoices_last_year
FROM   customer c
       INNER JOIN supplier_remit r
       ON (c.supplier_id = r.supplier_id)
       LEFT OUTER JOIN (
         SELECT customer_id,
                MAX(invoice_date) AS last_invoice_date,
                MAX(payment_method) KEEP (DENSE_RANK LAST ORDER BY invoice_date)
                  AS latest_payment_method,
                MAX(invoice_amount) KEEP (DENSE_RANK LAST ORDER BY invoice_date)
                  AS latest_invoice_amount,
                COUNT(
                  DISTINCT
                  CASE
                  WHEN invoice_date <  SYSDATE
                  AND  invoice_date >= TRUNC(SYSDATE, 'YY') 
                  THEN TRUNC(invoice_date, 'MM')
                  END
                ) AS missing_invoices_this_year,
                COUNT(
                  DISTINCT
                  CASE
                  WHEN invoice_date <  TRUNC(SYSDATE, 'YY') 
                  AND  invoice_date >= ADD_MONTHS(TRUNC(SYSDATE, 'YY'), -12)
                  THEN TRUNC(invoice_date, 'MM')
                  END
                ) AS missing_invoices_last_year
         FROM   invoice
         GROUP BY customer_id
       ) i
       ON (c.customer_id = i.customer_id)
WHERE  c.customer_status = 'Active';

Which, for the sample data:

CREATE TABLE customer (Customer_id, Customer_Account_number, Customer_Status, Supplier_id, Supplier_Remit_id) AS
SELECT 1, 1501, 'Active',   11, 111 FROM DUAL UNION ALL
SELECT 2, 1502, 'Inactive', 12, 112 FROM DUAL UNION ALL
SELECT 3, 1503, 'Active',   13, 113 FROM DUAL UNION ALL
SELECT 4, 1504, 'Active',   14, 114 FROM DUAL UNION ALL
SELECT 5, 1505, 'Inactive', 15, 115 FROM DUAL;

CREATE TABLE invoice (Invoice_Date, Invoice_Amount, Invoice_Number, Payment_Method, Customer_id) AS
SELECT DATE '2023-01-01',  100,  1000001, 'Cash',        1 FROM DUAL UNION ALL
SELECT DATE '2022-12-01',  150,  1000002, 'Credit Card', 1 FROM DUAL UNION ALL
SELECT DATE '2022-11-09',  200,  1000003, 'Credit Card', 1 FROM DUAL UNION ALL
SELECT DATE '2022-12-09',  300,  1000004, 'Cash',        2 FROM DUAL UNION ALL
SELECT DATE '2022-04-15', 1000,  1000005, 'Cash',        2 FROM DUAL UNION ALL
SELECT DATE '2022-04-15', 1000,  1000006, 'Credit Card', 3 FROM DUAL UNION ALL
SELECT DATE '2022-10-31',  250,  1000007, 'Cash',        4 FROM DUAL UNION ALL
SELECT DATE '2022-10-25',  250,  1000008, 'Cash',        4 FROM DUAL UNION ALL
SELECT DATE '2022-09-20',  130,  1000009, 'Credit Card', 5 FROM DUAL UNION ALL
SELECT DATE '2022-05-20',  120, 10000010, 'Credit Card', 5 FROM DUAL;

CREATE TABLE supplier (Supplier_Name, Supplier_id) AS
SELECT 'ABC',  11 FROM DUAL UNION ALL
SELECT 'ACCC', 12 FROM DUAL UNION ALL
SELECT 'ADEF', 13 FROM DUAL UNION ALL
SELECT 'AJKL', 14 FROM DUAL UNION ALL
SELECT 'AFLR', 15 FROM DUAL;

 
CREATE TABLE supplier_remit (City, Country, Supplier_Remit_id, Supplier_id) AS
SELECT 'Boston',  'US', 111, 11 FROM DUAL UNION ALL
SELECT 'Oak',     'US', 112, 12 FROM DUAL UNION ALL
SELECT 'Albany',  'US', 113, 13 FROM DUAL UNION ALL
SELECT 'Madison', 'US', 114, 14 FROM DUAL UNION ALL
SELECT 'Los Ang', 'US', 115, 15 FROM DUAL;

Outputs:

CUSTOMER_ID CUSTOMER_ACCOUNT_NUMBER CUSTOMER_STATUS COUNTRY LAST_INVOICE_DATE LATEST_PAYMENT_METHOD LATEST_INVOICE_AMOUNT MISSING_INVOICES_THIS_YEAR MISSING_INVOICES_LAST_YEAR
1 1501 Active US 2023-01-01 00:00:00 Cash 100 0 10
3 1503 Active US 2022-04-15 00:00:00 Credit Card 1000 1 11
4 1504 Active US 2022-10-31 00:00:00 Cash 250 1 11

fiddle

CodePudding user response:

In order to find what's missing, you have to first define what should be there, so you need to create a calendar of every month. Then you can use outer joins to the invoice table to find where there aren't any records for that month for that customer. There are lots of ways to write SQL to do this. Here's one:

WITH months AS(SELECT /*  MATERIALIZE */ *
                 FROM (SELECT 'Current' year,
                              ADD_MONTHS(TRUNC(SYSDATE,'YYYY'),ROWNUM-1) month_start
                         FROM [any table with at least 12 rows]
                        WHERE ROWNUM <= 12)
                 WHERE month_start < SYSDATE
               UNION ALL
               SELECT 'Previous' year,
                      ADD_MONTHS(TRUNC(ADD_MONTHS(SYSDATE,-12),'YYYY'),ROWNUM-1)
                 FROM [any table with at least 12 rows]
                WHERE ROWNUM <= 12)
SELECT customer.*,
       inv.invoice_amount most_recent_invoice_amount,
       inv.payment_method most_recent_payment_method,
       (SELECT COUNT(*)
          FROM months,
               invoice
         WHERE months.year = 'Current'
           AND months.month_start = TRUNC(invoice_date( ),'MM')
           AND invoice.customer_id( ) = customer.customer_id
           AND invoice.customer_id IS NULL) missed_current_year_months,
       (SELECT COUNT(*)
          FROM months,
               invoice
         WHERE months.year = 'Previous'
           AND months.month_start = TRUNC(invoice_date( ),'MM')
           AND invoice.customer_id( ) = customer.customer_id
           AND invoice.customer_id IS NULL) missed_previous_year_months 
  FROM customer
       OUTER APPLY (SELECT invoice_amount,
                           payment_method
                      FROM (SELECT invoice_amount,
                                   payment_method,
                                   ROW_NUMBER() OVER (ORDER BY invoice_date DESC) seq
                              FROM invoice
                             WHERE invoice.customer_id = customer.customer_id)
                     WHERE seq = 1) inv
  • Related