[英]Take two different values from a single SQL query
Is there a way to simplify/optimise this mysql/mariadb query?有没有办法简化/优化这个 mysql/mariadb 查询? 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:这可行但很难看,因为它重复了 JOINS 和 WHERE 子句:
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:
给定的名称是任意的,而不是根据 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 tab银行交易付款
| 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 tab银行交易
| name | date | docstatus |
---------------------------------
| doc1 | 2022-01-01 | 1 |
| doc2 | 2022-02-01 | 1 |
| doc3 | 2022-03-01 | 1 |
Required result: (60.00, doc3)所需结果:(60.00,doc3)
mariadb version: 10.2.27 mariadb 版本:10.2.27
We can try to use ROW_NUMBER
& SUM
window functions to make it.我们可以尝试使用
ROW_NUMBER
& SUM
窗口函数来实现。
ROW_NUMBER
get the lastest row of name by bt.date desc
ROW_NUMBER
通过bt.date desc
获取 name 的最后一行
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. OVER
子句对于窗口函数是必不可少的,它基于一组记录执行计算,并且PARTITION BY
定义了行被划分到的组。
More detail we can see Window Function Concepts and Syntax更多细节我们可以看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.感谢 D-Shih 对我不知道存在的窗口功能的建议和介绍。 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.对于由于分区而需要多个结果行的其他情况,将需要
ROW_NUMBER()
。
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.