由于某种原因,此查询最多需要5分钟才能执行。我已经将连接缓冲区扩展为1G,我对此查询进行了解释(结果为here)似乎没有任何迹象表明为什么这需要花费很多时间。在查询期间,CPU的所有8个内核都达到接近100%的使用率。
引擎是InnoDB。
所有表都有主键索引。
fun Filter[] = [] | Filter(x::xs) =
let
fun lessthan x = if x < 5 then x else 0
in
lessthan(x)::Filter(xs)
end;
最新解释
SELECT Concat(Concat(cust.first_name, ' '), cust.last_name) AS customerName,
TYPE.code AS transType,
ty1.nsfamount,
np.sumrebateamount,
trans.note_id AS note_id,
trans.createdate AS createdatestr,
n.totalamount,
n.currentfloat,
( ( n.costofborrowing * 100 ) / n.amounttolent ) AS fees,
n.amounttolent,
( 0 - ( trans.cashamount + trans.chequeamount
+ trans.debitamount
+ trans.preauthorizedamount ) ) AS paidamount,
sumpenaltyamount
FROM (SELECT *
FROM loan_transaction trans1
WHERE trans1.cashamount < 0
OR trans1.chequeamount < 0
OR trans1.debitamount < 0
OR trans1.preauthorizedamount < 0) trans
inner join customer cust
ON trans.customer_id = cust.customer_id
inner join (SELECT *
FROM lookuptransactiontypes ty
WHERE ty.code <> 'REB'
AND ty.code <> 'PN') TYPE
ON trans.transactiontype = TYPE.transactiontypesid
inner join note n
ON trans.note_id = n.note_id
inner join (SELECT note_id,
SUM(rebateamount) AS sumrebateamount
FROM note_payment np1
GROUP BY np1.note_id) np
ON trans.note_id = np.note_id
left join (SELECT note_id,
transactiontype,
( SUM(chequeamount) + SUM(cashamount)
+ SUM(debitamount) + SUM(preauthorizedamount) )AS
NSFamount
FROM (SELECT *
FROM loan_transaction trans4
WHERE trans4.cashamount > 0
OR trans4.chequeamount > 0
OR trans4.debitamount > 0
OR trans4.preauthorizedamount > 0)trans5
inner join (SELECT transactiontypesid
FROM lookuptransactiontypes ty2
WHERE ty2.code = 'NSF')type2
ON
trans5.transactiontype = type2.transactiontypesid
GROUP BY trans5.note_id) ty1
ON ty1.note_id = trans.refnum
left join (SELECT note_id AS noteid,
( SUM(tp.cashamount) + SUM(tp.chequeamount)
+ SUM(tp.debitamount)
+ SUM(tp.preauthorizedamount) ) AS sumpenaltyamount
FROM loan_transaction tp
inner join (SELECT transactiontypesid
FROM lookuptransactiontypes lp
WHERE lp.code = 'PN') lp
ON lp.transactiontypesid = tp.transactiontype
GROUP BY tp.note_id) p
ON p.noteid = trans.refnum
答案 0 :(得分:1)
您可以一次连接多个列(例如:CONCAT(column1,'',column2))
不需要在同一个表(或第一个FROM中的右侧)上使用内部联接执行子查询。只需将FROM直接放在子查询的主表上,然后在主查询的WHERE中移动子查询的过滤器
不确定,但似乎所有逻辑都基于每个note_id。如果确实如此,请在主查询的GROUP BY =&gt;中移动GROUP BY note_id。摆脱每个note_id进程的所有子查询,只需在想要的表上加入并在主查询SELECT中移动它们的SUM()和其他列选择
当你想拥有2个基于同一个表但具有不同过滤器的值时,你不需要创建子查询,你可以使用for(例如一个SUM())示例:
SUM(IF(COLUMN1 = YOUR_FILTER1或COLUMN1 = YOUR_FILTER2,COLUMN1,0))totalWithFILTER1andFILTER2 [...] GROUP BY note_id
仅供参考,因为我所说的可能看起来很模糊,我开始简化你的查询,但因为我不知道你想要实现什么(没有重构2 LEFT JOIN)而停止了那个废话。 这是查询(虽然无法测试):
SELECT
CONCAT(cust.first_name, ' ', cust.last_name) AS customerName,
TYPE.code AS transType,
ty1.nsfamount,
SUM(np.rebateamount) as sumrebateamount,
trans.note_id AS note_id,
trans.createdate AS createdatestr,
n.totalamount,
n.currentfloat,
((n.costofborrowing * 100) / n.amounttolent) AS fees,
n.amounttolent,
(0 - (trans.cashamount + trans.chequeamount
+ trans.debitamount
+ trans.preauthorizedamount)) AS paidamount,
sumpenaltyamount
FROM loan_transaction trans
INNER JOIN customer cust ON trans.customer_id = cust.customer_id
INNER JOIN lookuptransactiontypes TYPE ON trans.transactiontype = TYPE.transactiontypesid
INNER JOIN note n ON trans.note_id = n.note_id
INNER JOIN note_payment np ON trans.note_id = np.note_id
LEFT JOIN (SELECT
note_id,
transactiontype,
(SUM(chequeamount) + SUM(cashamount)
+ SUM(debitamount) + SUM(preauthorizedamount)) AS
NSFamount
FROM loan_transaction trans4
INNER JOIN lookuptransactiontypes type2 ON trans4.transactiontype = type2.transactiontypesid
WHERE (trans4.cashamount > 0
OR trans4.chequeamount > 0
OR trans4.debitamount > 0
OR trans4.preauthorizedamount > 0) AND type2.code = 'NSF'
GROUP BY trans5.note_id) ty1
ON ty1.note_id = trans.refnum
LEFT JOIN (SELECT
note_id AS noteid,
(SUM(tp.cashamount) + SUM(tp.chequeamount)
+ SUM(tp.debitamount)
+ SUM(tp.preauthorizedamount)) AS sumpenaltyamount
FROM loan_transaction tp
INNER JOIN (SELECT transactiontypesid
FROM lookuptransactiontypes lp
WHERE lp.code = 'PN') lp
ON lp.transactiontypesid = tp.transactiontype
GROUP BY tp.note_id) p
ON p.noteid = trans.refnum
WHERE
(trans.cashamount < 0
OR trans.chequeamount < 0
OR trans.debitamount < 0
OR trans.preauthorizedamount < 0)
AND TYPE.code <> 'REB'
AND TYPE.code <> 'PN'
GROUP BY trans.note_id;
答案 1 :(得分:0)
我同意@Aurelien的回答,为什么你加入一个派生表,同时你可以加入普通表并应用过滤器。为什么这样做
-- this will force a full scan on customer table and ignores the filter
select whatever
from transactions inner join
(
select * from customer
) customer on transactions.customer_id = customer.customer_id
where customer.customer_id = 1;
虽然你可以这样做
select whatever
from transactions inner join customer on transactions.customer_id = customer.customer_id
where customer.customer_id = 1;
除了@Aurelien回答,
恕我直言,您的查询问题是您需要所有客户的数据,因此无论此查询如何优化您还在进行全面扫描,您无法进行扩展,想象一下从现在起几年后你有100M的交易。
可能这不是您想要的,但分区/分页如此报告呢?用户通常不需要一次性展示整个客户,也不需要浪费资源。
我们的计划是做同样的工作,但仅限50位客户。
在你摆脱不必要的子查询后 - 如@Aurelien回答所示 - 更改他的查询的这一部分
FROM loan_transaction trans
INNER JOIN customer cust ON trans.customer_id = cust.customer_id
进入这个
FROM (SELECT * FROM customer LIMIT 50 OFFSET 0) cust
INNER JOIN loan_transaction trans ON trans.customer_id = cust.customer_id
请注意,偏移的分页不是缩放,因此如果您的customers表很大,您可以考虑another type of pagination