2017-10-05 20 views
0
SELECT Distinct org.id_name,org.id_region,org.id_inn,org.id_kpp,org.id_username, agreements.id_agr_code, 
agreements.id_crat, agreements.id_project_name, agreements.comment, agreements.comment2, agreements.id_factor, agreements.id_name, 
month1.id_date_money,month1.id_done,month2.id_date_money,month2.id_done,month3.id_date_money,month3.id_done,month4.id_date_money, 
month4.id_done,month5.id_date_money,month5.id_done,month6.id_date_money,month6.id_done FROM agreements 
inner join org on (org.id_org=agreements.id_org) 
LEFT OUTER JOIN money as month1 ON (agreements.id_agr = month1.id_dogovor) and (month1.id_date_money is NULL OR month1.id_date_money=:Month1) 
LEFT OUTER JOIN money as month2 ON (agreements.id_agr = month2.id_dogovor) and (month2.id_date_money is NULL OR month2.id_date_money=:Month2) 
LEFT OUTER JOIN money as month3 ON (agreements.id_agr = month3.id_dogovor) and (month3.id_date_money is NULL OR month3.id_date_money=:Month3) 
LEFT OUTER JOIN money as month4 ON (agreements.id_agr = month4.id_dogovor) and (month4.id_date_money is NULL OR month4.id_date_money=:Month4) 
LEFT OUTER JOIN money as month5 ON (agreements.id_agr = month5.id_dogovor) and (month5.id_date_money is NULL OR month5.id_date_money=:Month5) 
LEFT OUTER JOIN money as month6 ON (agreements.id_agr = month6.id_dogovor) and (month6.id_date_money is NULL OR month6.id_date_money=:Month6) 
where agreements.id_old=:Archive 
and case when :region is null then org.id_region=org.id_region else FIND_IN_SET(org.id_region, :region) end 
and case when :users is null then org.id_user=org.id_user else FIND_IN_SET(org.id_user, :users) end 
and case when :agrtype is null then agreements.id_type=agreements.id_type else FIND_IN_SET(agreements.id_type, :agrtype) end 
and case when :agrproject is null then agreements.id_project_name=agreements.id_project_name else FIND_IN_SET(agreements.id_project_name, :agrproject) end 
ORDER BY org.id_name 

在MySQL這個SQL語句佔用很多的時間才能完成,並在某一時刻掛在BD,因爲它創造了很多這是根說連接的「複製到tmp_table的」。錯誤消息顯示「太多連接到BD」。的SQL語句創建許多連接,並掛起DB

我認爲這是因爲FIND_IN_SET,但我不確定。我找不到一種不同的方式來重寫這個SQL,以便它執行得更快,並且不會創建所有這些連接(它會一直創建它們直到它填充到最大)。

這個想法是顯示哪些組織在定義的月份中支付了哪些協議,哪些沒有支付。區域過濾器的編號爲01,05,09,23,26,91和e.t.c,用戶的過濾器位於user_id整數中。 agrtypes的過濾器在字符串中,agrprojects也在字符串中。 ID_old是一個布爾標誌。 ID_agr,ID_Dogovor和id_org是主鍵Integer。

+1

當你還沒有標準化數據庫,但決定在列中使用逗號分隔的列表,而您也決定不考慮速度。爲了知道哪個記錄包含某個區域,例如必須讀取和檢查所有記錄,而使用org_region表,DBMS可能會使用索引。 –

回答

1

agreements.id_old一個ID或只是一些標誌,指示該ID是舊的格式或類似的?如果它真的是一個ID,它可能不會經常出現在表中。甚至只是一次?然後,列上的索引應該使訪問速度非常快。您還應該在money.id_dogovor上有索引。

我建議如下指標:

create index idx1 on agreements(id_old, id_org, id_agr); 
create index idx2 on money(id_dogovor, id_date_money, id_done); 

(我推測,在org(id_org)唯一索引存在,因爲這似乎是表的主鍵)

+0

id_old是一個布爾標誌。 – SovereignSun

+0

爲什麼查詢會創建大量的連接,指出「複製到tmp_table」?因爲這個查詢失敗,沒有人可以連接到數據庫,直到他們自動終止。 – SovereignSun

+0

謝謝,最終這工作。 – SovereignSun