Probably this simplification works (HAVING instead of extra layer):
select id, sum(poqty) as poqty,sum(outqty) as outqty from (
select id, Quantity as poqty, 0 as outqty from po where active
union all
select poid as id, 0 as poqty, qty as qty from invoicedetail where active
) as a where id group by id
HAVING poqty>outqty
You have to scan 210772 +... rows -- that takes time. Do you really need 500K rows output?
Let's flip it around -- co the SUMs first.
SELECT id, SUM(Quantity) AS poqty FROM po WHERE active GROUP BY id;
SELECT poid, SUM(qty) AS outqty FROM invoicedetail WHERE active GROUP BY poid;
Then JOIN those ON id=poid
SELECT p.id, p,poqty, i.outqty
FROM ( SELECT id, SUM(Quantity) AS poqty FROM po WHERE active GROUP BY id ) AS p
JOIN ( SELECT poid, SUM(qty) AS outqty FROM invoicedetail WHERE active GROUP BY poid ) AS i
ON p.id = i.poid
WHERE p.poqty > i.outqty;
How many rows in each of the subqueries I am suggesting? The SELECT, as it stands, will
1. create temp tables for each of the two subqueries. These will have no indexes
2. walk through one of the subqueries
3. for each row there, do a table scan of the other temp table
4. do the WHERE
If both temp tables are rather large, then you need to put one of the subqueries in a TEMPORARY TABLE and add an index.