Damien Moran
Damien Moran

Reputation: 135

SQL: Adding two summed fields and comparing the summed value with another field value

OK guys last question on this topic (I HOPE).

What I need to do is sum fields from two different tables, add them together, and check whether this total is greater than that customers credit limit.

I have broken down my problem into smaller tasks so that I could try to come up with the overall solution. (These smaller codes work correctly for me, but when combined in the third piece of code, they sum incorrectly). First I have calculated the first summed field as shown:

 --summmed open invoices

 SELECT company,  sum(unit_price * invoice_qty) as open_invoices

 FROM 
  (SELECT arc.company, ard.unit_price, ard.invoice_qty, arc.credit_limit
   FROM iqms.arprepost_detail ard, iqms.arprepost arp, iqms.arcusto arc
   WHERE ard.arprepost_id = arp.ID
       AND arp.arcusto_id = arc.ID)

 GROUP BY company
 ORDER BY company;

The figures in this are coming out correctly when summed, I have checked manually. Next I have summed the other field I need as shown:

 --summed open orders

 SELECT company, (sum (unit_price * total_qty_ord)) as total_open_orders

 FROM 
   (SELECT arc.company, od.unit_price, od.total_qty_ord, arc.credit_limit   
    FROM iqms.arcusto arc, iqms.orders o, iqms.ord_detail od
    WHERE od.orders_id = o.ID
       AND o.arcusto_id = arc.ID
       AND (od.cumm_shipped < od.total_qty_ord  OR od.cumm_shipped IS NULL))

 GROUP BY company
 ORDER BY company;

Again these figures are coming out correctly on manual inspection.

What I need now is to add these two calculations together and check whether that figure is greater than the 'credit_limit' field for that customer. I have written code for this but the figures are coming out way over what they should (this code is given below).

 --summmed open invoices + open orders

  SELECT company, credit_limit, 
        round(sum(i_up * invoice_qty)) AS total_invoices, 
        round(sum (o_up * total_qty_ord)) AS total_orders,
        round(sum(i_up * invoice_qty) + sum (o_up * total_qty_ord)) as overall_total

 FROM 
   (SELECT arc.company, arc.credit_limit, ard.unit_price as i_up, ard.invoice_qty, od.unit_price as o_up, od.total_qty_ord 
    FROM iqms.arprepost_detail ard, iqms.arprepost arp, iqms.arcusto arc, iqms.orders o, iqms.ord_detail od
    WHERE 
       ard.arprepost_id = arp.ID      
       AND arp.arcusto_id = arc.ID
       AND od.orders_id = o.ID
       AND o.arcusto_id = arc.ID
       AND (od.cumm_shipped < od.total_qty_ord  OR od.cumm_shipped IS NULL)
   )

 GROUP BY company, credit_limit
 HAVING ((sum(i_up * invoice_qty)) + (sum (o_up * total_qty_ord)) > credit_limit)
 ORDER BY company;

I'm not sure where I'm going wrong. Maybe its a simple fix or maybe there's something wrong with my logic. Any insight is greatly appreciated. Thanks a lot for the continued support.

Upvotes: 2

Views: 1863

Answers (2)

GarethD
GarethD

Reputation: 69789

My First observation would be that you should be using explicit joins instead of implicit joins, implict joins are 20 years out of date

You can't combine your 2 queries as you have done because they are from different tables, doing so with implicit joins is causing a cross join. I think the most simple way to do this would be to use 2 left joins for each of the queries:

SELECT  arc.Company,
        arc.Credit_Lime,
        COALESCE(Open_Orders, 0) AS Open_Orders,
        COALESCE(Open_Invoices, 0) AS Open_Invoices
        COALESCE(Open_Orders, 0) + COALESCE(Open_Invoices, 0) AS Total_Amount
FROM    iqms.arcusto arc
        LEFT JOIN
        (   SELECT  o.arcusto_ID
                    SUM(od.unit_price * od.total_qty_ord) AS Open_Orders
            FROM    iqms.orders o
                    INNER JOIN iqms.ord_detail od
                        ON od.orders_ID = o.ID
            WHERE   od.Cumm_Shipped < od.Total_qty_Ord
            OR      od.Cumm_Shipped IS NULL
            GROUP BY o.arcusto_ID
        ) openOrders
            ON openOrders.Arcusto_ID = arc.ID
        LEFT JOIN
        (   SELECT  arp.arcusto_id,
                    SUM(Unit_Price * Invoice_Quantity) AS Open_Invoices
            FROM    iqms.arprepost_detail ard
                    INNER JOIN iqms.arprepost arp
                        ON  ard.arprepost_id = arp.ID
            GROUP BY arp.arcusto_id
        ) OpenInvoices
            ON OpenInvoices.Arcusto_ID = arc.ID
WHERE   COALESCE(Open_Orders, 0) + COALESCE(Open_Invoices, 0) > arc.Credit_Limit;

You could also UNION THE two queries as follows:

SELECT  arc.Company,
        arc.Credit_Lime,
        SUM(COALESCE(Open_Orders, 0)) AS Open_Orders
FROM    iqms.arcusto arc
        LEFT JOIN
        (   SELECT  o.arcusto_ID
                    SUM(od.unit_price * od.total_qty_ord) AS Open_Orders
            FROM    iqms.orders o
                    INNER JOIN iqms.ord_detail od
                        ON od.orders_ID = o.ID
            WHERE   od.Cumm_Shipped < od.Total_qty_Ord
            OR      od.Cumm_Shipped IS NULL
            GROUP BY o.arcusto_ID
            UNION ALL
            SELECT  arp.arcusto_id,
                    SUM(Unit_Price * Invoice_Quantity) AS Open_Invoices
            FROM    iqms.arprepost_detail ard
                    INNER JOIN iqms.arprepost arp
                        ON  ard.arprepost_id = arp.ID
            GROUP BY arp.arcusto_id
        ) OpenInvoices
            ON OpenInvoices.Arcusto_ID = arc.ID
GROUP BY arc.Company, arc.Credit_Limit
HAVING  SUM(Open_Orders) > arc.Credit_Limit;

But I think the first offers more flexibility in identifying whether credit limits are exceeded by Open_Orders or Open_Invoices

Upvotes: 1

Vincent Malgrat
Vincent Malgrat

Reputation: 67762

In this case since the two queries are distinct, I suggest you use UNION ALL:

SELECT company, SUM(open_invoices) total /*should rename the column in query 1*/ 
  FROM ([QUERY1]
        UNION ALL
        [QUERY2])
 GROUP by company

Upvotes: 1

Related Questions