我有一个查询适用于1000条或更少的记录,但现在我需要优化它以获得50,000条以上的记录,当我在它上面运行它只是停止...
这是我的代码:
SELECT
b1.account_num,b1.effective_date as ed1,b1.amount as am1,
b2.effective_date as ed2,b2.amount as am2
FROM bill b1
left join bill b2 on (b1.account_num=b2.account_num)
where b1.effective_date = (select max(effective_date) from bill where account_num = b1.account_num)
and (b2.effective_date = (select max(effective_date) from bill where account_num = b1.account_num and effective_date < (select max(effective_date) from bill where account_num = b1.account_num)) or b2.effective_date is null)
ORDER BY b1.effective_date DESC
我的目标是从一张包含许多记录的表格中获取最新的两个生效日期和金额。
答案 0 :(得分:1)
Here is a working answer from your SQL-Fiddle baseline
首先,内部preQuery获取每个帐户的最大日期。然后将其加入到每个帐户的帐单表中,并且生效日期小于已检测到的最大值。
然后加入各自的账单以获取金额。
select
FB1.account_num,
FB1.effective_date as ed1,
FB1.amount as am1,
FB2.effective_date as ed2,
FB2.amount as am2
from
( select
pq1.account_num,
pq1.latestBill,
max( b2.effective_date ) as secondLastBill
from
( SELECT
b1.account_num,
max( b1.effective_date ) latestBill
from
bill b1
group by
b1.account_num ) pq1
LEFT JOIN bill b2
on pq1.account_num = b2.account_num
AND b2.effective_date < pq1.latestBill
group by
pq1.account_num ) Final
JOIN Bill FB1
on Final.Account_Num = FB1.Account_Num
AND Final.LatestBill = FB1.Effective_Date
LEFT JOIN Bill FB2
on Final.Account_Num = FB2.Account_Num
AND Final.secondLastBill = FB2.Effective_Date
ORDER BY
Final.latestBill DESC
答案 1 :(得分:0)
在mysql中,像row_number
这样的窗口分析函数不存在,所以我们可以使用变量来模拟相同的。
好处是,用这种方法只扫描一次表。
row_number分配给每个分区,根据(帐号,生效日期)划分,每个分区只选择2行。
select account_num,
max(case when row_number =1 then effective_date end) as ed1,
max(case when row_number =1 then amount end) as am1,
max(case when row_number =2 then effective_date end) as ed2,
max(case when row_number =2 then amount end )as am2
from (
select account_num, effective_date, amount,
@num := if(@prevacct= account_num , @num + 1, 1) as row_number,
@prevacct := account_num as dummy
from bill, (select @num:=0, @prevacct := '' ) as var
order by account_num , effective_date desc
)T
where row_number <=2
group by account_num