mysql - 左连接——如何提高效率?

标签 mysql

我写了一个难以阅读的查询,而且恐怕效率会很差。在将每个表中的consumerid 与consumerdata.consumerid 匹配方面,可以更有效地编写此查询吗?

select 

consumerdata.consumerid, 
signupdate, 
city, 
state, 
year(DOB), 
topaffiliate, 
activestatus, 
lastuseddate,

(select sum(achload.transactionamount) from achload where achload.consumerid = consumerdata.consumerid) as Total_ACH,
(select sum(billpay.transactionamount) from billpay where billpay.consumerid = consumerdata.consumerid) as Bill_Pay,
(select sum(recharge.transactionamount) from recharge where recharge.consumerid = consumerdata.consumerid) as Revenue,
(select count(cash.consumerid) from Cash where cash.consumerid = consumerdata.consumerid) as Cash__TXNs,
(select sum(moneytransfer.transactionamount) from moneytransfer where moneytransfer.consumerid = consumerdata.consumerid) as Transfer,
(select sum(moneytransfer.commissionfeeamount) from moneytransfer where moneytransfer.consumerid = tbl_accounts_consumerdata.consumerid) as commission_fee,
(select count(interchangetransactions.transactiondescription) from interchangetransactions where interchangetransactions.transactiondescription = "Withdrawal" and interchangetransactions.consumerid = consumerdata.consumerid) as Withdrawals,
(select count(interchangetransactions.responsecode) from interchangetransactions where interchangetransactions.responsecode in (01) and interchangetransactions.consumerid = consumerdata.consumerid and interchangetransactions.transactiondescription = "Withdrawal") as Code_01,
(select count(interchangetransactions.responsecode) from interchangetransactions where interchangetransactions.responsecode in (02) and interchangetransactions.consumerid = consumerdata.consumerid and interchangetransactions.transactiondescription = "Withdrawal" ) as Code_02,
(select count(interchangetransactions.transactiondescription) from interchangetransactions where interchangetransactions.transactiondescription IN ("2 Cash Advance", "1 Cash Advance") and interchangetransactions.consumerid = consumerdata.consumerid) as Cash_Advance_Count,
(select count(interchangetransactions.transactiondescription) from interchangetransactions where interchangetransactions.transactiondescription IN ("Balance") and interchangetransactions.consumerid = consumerdata.consumerid) as Inquiry_Count,
(select sum(interchangetransactions.transactionamount) from interchangetransactions where interchangetransactions.transactiontypecode = 195 and interchangetransactions.consumerid = consumerdata.consumerid)  as Intnl_TXN_Sum,
(select count(interchangetransactions.transactionamount) from interchangetransactions where interchangetransactions.transactiontypecode = 195 and interchangetransactions.consumerid = consumerdata.consumerid)  as Intnl_TXN_Count


from
consumerdata

left join achload
on achload.consumerid=consumerdata.consumerid

left join  billpay
on billpay.consumerid = consumerdata.consumerid

left join recharge
on recharge.consumerid = consumerdata.consumerid

left join cash
on cash.consumerid = consumerdata.consumerid

left join moneytransfer
on moneytransfer.consumerid = consumerdata.consumerid

left join interchangetransactions
on interchangetransactions.consumerid = consumerdata.consumerid

where consumerdata.signupdate between date(20120101) and curdate()
group by consumerdata.consumerid order by signupdate asc;

最佳答案

由于您没有从任何事务表中选择任何内容,因此一个简单的改进就是删除所有 LEFT JOIN 子句。它们没有用于任何用途,因为您是从相关子查询中获取总计的。这会导致数据库在所有表之间创建巨大的叉积,然后在底部执行 GROUP BY 时将其丢弃。

另一种方法是连接计算每个事务表的分组总计的子查询,而不是关联子查询。

select 
    c.consumerid, signupdate, state, year(DOB), topaffiliate, activestatus, lastuseddate,
    IFNULL(Total_ACH, 0) AS Total_ACH, IFNULL(Bill_Pay, 0) AS Bill_Pay, IFNULL(Revenue, 0) AS Revenue, 
    IFNULL(Cash__TXNs, 0) AS Cash__TXNs, ...
FROM consumerdata AS c
LEFT JOIN (
    SELECT consumerid, SUM(transactionamount) AS Total_ACH
    FROM achload
    GROUP BY consumerid) AS a ON a.consumerid = c.consumerid
LEFT JOIN (
    SELECT consumerid, SUM(transactionamount) AS Bill_Pay
    FROM billpay
    GROUP BY consumerid) AS b ON b.consumerid = c.consumerid
LEFT JOIN (
    SELECT consumerid, SUM(transactionamount) AS Revenue
    FROM recharge
    GROUP BY consumerid) AS r ON r.consumerid = c.consumerid
LEFT JOIN (
    SELECT consumerid, COUNT(*) AS Cash__TXNs
    FROM Cash
    GROUP BY consumerid) AS cash ON cash.consumerid = c.consumerid
...
WHERE c.signupdate between DATE(20120101) and CURDATE()
ORDER BY signupdate ASC

我不确定哪种方式实际上会更快 - 这可能取决于注册日期超出您指定范围的消费者的交易表中有多少数据。尝试两者,看看哪个更好。

关于mysql - 左连接——如何提高效率?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39643762/

相关文章:

mysql - 如何查找和禁用 MySQL 严格模式?

java - 重复更新 MySQL 表中的行

mysql - MySQL中的日期差异来计算年龄

php - mySQL 查询似乎使服务器崩溃

mysql - 用于存储用户 Facebook 点赞数的数据库设计

php - 上传sql文件时mysql数据库显示错误

mysql - 使用 LOAD DATA INFILE 在 Mysql 中导入数据时的混淆行为

php - 在哪里可以找到将 Twitter 集成到我的站点的代码?

mysql - SQL 特定语句查询

c# - 使用 C# 连接到 MySQL Web 服务器