Is there a way to simplify/optimise this mysql/mariadb query? Ultimately I need two individual pieces of data from a single query: the latest transaction name and sum of all transaction payment amounts.
This works but is ugly because it repeats the JOINS and WHERE clauses:
SELECT
SUM(btp.allocated_amount),
(
SELECT
bt.name
FROM
`tabBank Transaction Payments` as btp
LEFT JOIN
`tabBank Transaction` bt ON bt.name=btp.parent
WHERE
btp.payment_document = 'Journal Entry'
AND
bt.docstatus = 1
ORDER BY
bt.date desc
LIMIT 1
) AS name
FROM
`tabBank Transaction Payments` as btp
LEFT JOIN
`tabBank Transaction` bt ON bt.name=btp.parent
WHERE
btp.payment_document = 'Journal Entry'
AND
bt.docstatus = 1;
I thought something like this would work but it doesn't. The name given is arbitrary and not the first according to the ORDER BY:
SELECT
(SELECT SUM(allocated_amount)),
(SELECT name LIMIT 1)
FROM
(
SELECT
btp.allocated_amount,
bt.name
FROM
`tabBank Transaction Payments` as btp
LEFT JOIN
`tabBank Transaction` bt ON bt.name=btp.parent
WHERE
btp.payment_document = 'Journal Entry'
AND
bt.docstatus = 1
ORDER BY
bt.date desc
) AS temp;
Edit:
Example data (NOTE: example has been simplified):
tabBank Transaction Payments
| parent | payment_document | allocated_amount |
------------------------------------------------
| doc1 | Journal Entry | 10.00 |
| doc1 | Journal Entry20 | 4000.00 |
| doc2 | Journal Entry | 20.00 |
| doc2 | Journal Entry20 | 5000.00 |
| doc3 | Journal Entry | 30.00 |
| doc3 | Journal Entry20 | 6000.00 |
tabBank Transaction
| name | date | docstatus |
---------------------------------
| doc1 | 2022-01-01 | 1 |
| doc2 | 2022-02-01 | 1 |
| doc3 | 2022-03-01 | 1 |
Required result: (60.00, doc3)
mariadb version: 10.2.27
We can try to use ROW_NUMBER
& SUM
window functions to make it.
ROW_NUMBER
get the lastest row of name by bt.date desc
OVER
clause is essential to window functions, that perform calculations based on a set of records and PARTITION BY
defines the groups into which the rows are divided.
More detail we can see Window Function Concepts and Syntax
SELECT total_allocated_amount,name
FROM (
SELECT
SUM(btp.allocated_amount) OVER() total_allocated_amount,
ROW_NUMBER() OVER(ORDER BY bt.date desc) rn,
bt.name
FROM
`tabBank Transaction Payments` as btp
LEFT JOIN
`tabBank Transaction` bt ON bt.name=btp.parent
WHERE
btp.payment_document = 'Journal Entry'
AND
bt.docstatus = 1
) t1
WHERE rn = 1
Thanks to D-Shih for the suggestion and intro to window functions which I didn't know existed. I simplified and ended up with this.
For other scenarios where you need more than one result row due to partitioning, the ROW_NUMBER()
will be required.
SELECT *
FROM (
SELECT
SUM(btp.allocated_amount) OVER() total_allocated_amount,
FIRST_VALUE(bt.name) OVER(ORDER BY bt.date desc) latest_name
FROM
`tabBank Transaction Payments` as btp
LEFT JOIN
`tabBank Transaction` bt ON bt.name=btp.parent
WHERE
btp.payment_document = 'Journal Entry'
AND
bt.docstatus = 1
) t1
LIMIT 1
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.