5

Just started an internship and have been tasked with some SQL. Finding it somewhat tricky. Appreciate any help. Thanks!

The task:

"Would it be possible to write an alert for the following. Show all customers who when Open sales orders due in the next month are combined (added) with open sales invoices, they exceed their credit limit."

My proposed logic:

  1. First what I want to do is SUM all sales orders, within the next month, for each customer (in the SALES table).

  2. Next, SUM all open invoices for each customer, i.e. work out total amount each customer owes (in the INVOICES table).

  3. I then want to add the results of 1 and 2 together, by corresponding customer_id

  4. Next compare the calculation from 3 above to see whether its greater than each customers credit limit.

If the summed total in 3 exceeds the credit limit then only these companies should be displayed in the generated table. The ideal format for the resulting table would be

Cust_ID|Name|Sum_sales_orders (1.above)|Sum_open_invoices (2.above)| Total_orders&invoices
----------------------------------------------------------------------------
   1   |  A |  25000                   |  333                      | 25333 
       |    |                          |                           |

The code I have so far is

 SELECT arc.company, arc.credit_limit, 
     sum (ard.unit_price * ard.invoice_qty) as open_invoice_total, 
     sum (od.total_qty_ord * od.unit_price) as open_orders_total
 FROM iqms.arprepost_detail ard, iqms.arprepost arp, iqms.arcusto arc, iqms.ord_detail od, iqms.orders o
 WHERE ard.arprepost_id = arp.id 
     and arc.id = o.arcusto_id and o.id = od.orders_id
     and arp.arcusto_id = arc.id
  GROUP BY arc.company, arc.credit_limit

I think that this is calculating the correct totals in the sum () functions? or am i wrong? How can I add open_invoice_total and open_orders_total? and then compare them against the credit_limit?

I hope you guys understand what I am trying to do. Thanks for the help in advance! :)

Damien Moran
  • 135
  • 2
  • 13
  • 1
    `SELECT arc.company.......GROUP BY .....HAVING sum (ard.unit_price * ard.invoice_qty) + sum (od.total_qty_ord * od.unit_price) >arc.credit_limit` – Gaurav Soni Nov 23 '12 at 11:18

1 Answers1

3

You can use the HAVING clause to check whether the sum of the totals exceed the credit limit, like so. I've also replaced the joins in the WHERE clause with INNER JOINS, for readability sake.

 SELECT arc.company, arc.credit_limit, 
       sum(ard.unit_price * ard.invoice_qty) as open_invoice_total, 
       sum(od.total_qty_ord * od.unit_price) as open_orders_total
 FROM iqms.arprepost_detail ard 
        INNER JOIN iqms.arprepost arp ON ard.arprepost_id = arp.id
        INNER JOIN iqms.arcusto arc ON arp.arcusto_id = arc.id
        INNER JOIN iqms.ord_detail od ON o.id = od.orders_id
        INNER JOIN iqms.orders o ON arc.id = o.arcusto_id 
  GROUP BY arc.company, arc.credit_limit
  HAVING sum(ard.unit_price * ard.invoice_qty) + sum(od.total_qty_ord * od.unit_price) > arc.credit_limit;

Edit

Just to clarify Dems comment, GROUP BY doesn't allow the specification of aliases, hence the above query 'repeats' the sum in the SELECT and in the HAVING. This can be eliminated with nesting, although note that the HAVING is switched with a WHERE. So a DRYer version of the query is:

SELECT company, credit_limit, open_invoice_total, open_orders_total
FROM
(
     SELECT arc.company, arc.credit_limit, 
           sum(ard.unit_price * ard.invoice_qty) as open_invoice_total, 
           sum(od.total_qty_ord * od.unit_price) as open_orders_total
     FROM iqms.arprepost_detail ard 
            INNER JOIN iqms.arprepost arp ON ard.arprepost_id = arp.id
            INNER JOIN iqms.arcusto arc ON arp.arcusto_id = arc.id
            INNER JOIN iqms.ord_detail od ON o.id = od.orders_id
            INNER JOIN iqms.orders o ON arc.id = o.arcusto_id 
      GROUP BY arc.company, arc.credit_limit
) AS nested
WHERE (open_invoice_total + open_orders_total) > arc.credit_limit;

And, if you prefer, a CTE may make this more readable:

;WITH nested AS
(
     SELECT arc.company, arc.credit_limit, 
           sum(ard.unit_price * ard.invoice_qty) as open_invoice_total, 
           sum(od.total_qty_ord * od.unit_price) as open_orders_total
     FROM iqms.arprepost_detail ard 
            INNER JOIN iqms.arprepost arp ON ard.arprepost_id = arp.id
            INNER JOIN iqms.arcusto arc ON arp.arcusto_id = arc.id
            INNER JOIN iqms.ord_detail od ON o.id = od.orders_id
            INNER JOIN iqms.orders o ON arc.id = o.arcusto_id 
      GROUP BY arc.company, arc.credit_limit
)
SELECT company, credit_limit, open_invoice_total, open_orders_total
  FROM nested
  WHERE (open_invoice_total + open_orders_total) > arc.credit_limit;
Community
  • 1
  • 1
StuartLC
  • 104,537
  • 17
  • 209
  • 285
  • 2
    +1 : Another option, that I somewhat prefer *(as it keeps to the Don't Repeat Yourself principle)* is to wrap the query in an outer query `SELECT * FROM (theQuery) WHERE a+b > c` so as to avoid writing out the calculations for `a` and `b` twice. *[There is also no real measurable performance difference.]* – MatBailie Nov 23 '12 at 11:38