On Mon Sep 11, 2017 at 08:40:41AM +0200, Frank Millman wrote:
> I could structure it like this (pseudo code) -
>
> SELECT acc_no, acc_name,
> (SELECT SUM(invoice_bal) FROM invoices
> WHERE invoice_date <= date_5) AS 120_days,
> (SELECT SUM(invoice_bal) FROM invoices
> WHERE invoice_date > date_5 AND invoice_date <= date_4) AS 90_days,
> (SELECT SUM(invoice_bal) FROM invoices
> WHERE invoice_date > date_4 AND invoice_date <= date_3) AS 60_days,
> (SELECT SUM(invoice_bal) FROM invoices
> WHERE invoice_date > date_3 AND invoice_date <= date_2) AS 30_days,
> (SELECT SUM(invoice_bal) FROM invoices
> WHERE invoice_date > date_2 AND invoice_date <= date_1) AS current
> FROM debtors_table
>
> This works, but it requires 5 separate scans of the invoice table,
> which is inefficient.
You can achieve the same result with a single table scan using CASE
statements:
SELECT
acc_no,
acc_name,
SUM(
CASE WHEN
invoice_date <= date_5
THEN
invoice_bal
ELSE
0
END
) AS 120_days,
SUM(
CASE WHEN
invoice_date > date_5 AND invoice_date <= date_4
THEN
invoice_bal
ELSE
0
END
) AS 90_days,
-- .......
SUM(
CASE WHEN
invoice_date > date_2 AND invoice_date <= date_1
THEN
invoice_bal
ELSE
0
END
) AS current
FROM
debtors_table
LEFT JOIN
invoices
ON
invoices.debtor_id = debtors_table.id
If your time periods are not exhaustive (covering all time) then you
can perhaps be more efficient again by moving the filtering into the
join clause:
SELECT
acc_no,
acc_name,
SUM(i_90.invoice_bal) AS 90_days,
SUM(i_current.invoice_bal) AS current
FROM
debtors_table
LEFT JOIN
invoices i_90
ON
i_90.debtor_id = debtors_table.id AND
i_90.invoice_date > date_5 AND
i_90.invoice_date <= date_4
LEFT JOIN
invoices i_current
ON
i_current.debtor_id = debtors_table.id AND
i_current.invoice_date > date_2 AND
i_current.invoice_date <= date_1
ORDER BY
...
For the above an index on invoices(debtor_id,invoice_date) would be
appropriate.
Also in case you weren't aware, the SUM() function in my second example
could produce NULL values. You may be better served in that instance by
CAST(TOTAL(i_current.invoice_bal) AS INTEGER).
--
Mark Lawrence
_______________________________________________
sqlite-users mailing list
[email protected]
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users