2016-12-26 53 views
-1

我現有的SQL查詢條件數據從各種表中獲取非常緩慢,需要了解如何優化查詢。如何優化sqlite_3查詢?

現有查詢嘗試從某個條件的「材料」表中獲取材料信息。如果'Config'表中有'printer',則只返回'Config'表中'materials'的信息。如果「配置」表中沒有「打印機」,則從「可用材料」表中返回所有材料的信息。這是使用大小寫和左連接處理的。但是必要的表達式在「連接」和「where」子句中重複出現。因此需要一種方法來存儲某些子查詢的「結果」,並稍後再使用它。我有sqlite的查詢,看起來像這樣: -

select m.name from material m 

left join available_material_printmode_config ac on ac.material_name = m.name and 
(SELECT EXISTS (SELECT 1 FROM available_material_printmode_config 
WHERE printer_name ='123' LIMIT 1)) and 
(SELECT case when material_name is null then 0 else 1 end 
FROM available_material_printmode_config WHERE printer_name ='123' 
and printmode_name = '2' LIMIT 1) 

left join available_materials am1 on am1.material_name = m.name 
and ((SELECT EXISTS (SELECT 1 FROM available_material_printmode_config 
WHERE printer_name ='123' LIMIT 1)) !=1 
or ((SELECT EXISTS (SELECT 1 FROM available_material_printmode_config 
WHERE printer_name ='123' LIMIT 1)) 
and (SELECT case when material_name is null then 1 else 0 end 
FROM available_material_printmode_config WHERE printer_name ='123' 
and printmode_name = '2' LIMIT 1))) 

where 
case 
when 'true' == (select case when exists 
(select distinct 1 from available_material_printmode_config where printer_name = '123') 
THEN 'true' ELSE 'false' END) 
and (SELECT case when material_name is null then 0 else 1 end 
FROM available_material_printmode_config WHERE printer_name ='123' 
and printmode_name = '2' LIMIT 1) 
then 
ac.printer_name = '123' and ac.printmode_name = '2' 
else 
am1.printer_name = '123' 
end 

想知道是否有任何方式再使用下文提到的sql語句的結果,因爲它們是重複的:

(SELECT EXISTS (SELECT 1 FROM available_material_printmode_config 
WHERE printer_name ='123' LIMIT 1)) 

(SELECT case when material_name is null then 0 else 1 end 
FROM available_material_printmode_config 
WHERE printer_name ='123' and printmode_name = '2' LIMIT 1) 

另外我想出了這樣的事情: -

with 
printercheck as (SELECT EXISTS (SELECT 1 FROM available_material_printmode_config 
WHERE printer_name ='123' LIMIT 1) as p), 
materialcheck as (SELECT case when material_name is null then 0 else 1 end as m 
FROM available_material_printmode_config WHERE printer_name ='123' 
and printmode_name = '2' LIMIT 1) 

select m.name from material m 

left join available_material_printmode_config ac on ac.material_name = m.name 
and (select p from printercheck limit 1) 
and (select m from materialcheck limit 1) 

left join available_materials am1 on am1.material_name = m.name 
and ((select p from printercheck limit 1) != 1 
or ((select p from printercheck limit 1) 
and (select m from materialcheck limit 1) !=1)) 

where 
case 
when (select p from printercheck limit 1) and (select m from materialcheck limit 1) 
then 
ac.printer_name = '123' and ac.printmode_name = '2' 
else 
am1.printer_name = '123' 
end 

這是我現在使用的最終查詢:從接受的答案靈感

select m.name, m.color from material m inner join 
available_material_printmode_config ac on ac.material_name is not null 
and m.name=ac.material_name  
where ac.printmode_name='2' and ac.printer_name='123' 
UNION 
select m.name,m.color from material m 
inner join available_materials am on m.name=am.material_name 
where (not exists (select distinct 1 from available_material_printmode_config 
where printer_name = am.printer_name limit 1) 
or exists (select 1 from available_material_printmode_config 
where printer_name = am.printer_name and printmode_name = '2' 
and material_name is null LIMIT 1)) and am.printer_name='123'; 

我原來的查詢有28步,aleternative一個有20個步驟和最終的查詢有9個步驟。步驟基本上算我使用解釋查詢計劃 sql命令。

回答

2

考慮你的兩組聯合查詢。雖然沒有發佈數據或架構,但下面可能需要調整。此外,子查詢現在相關外部查詢行:

SELECT m.name 
FROM material m 
LEFT JOIN available_material_printmode_config ac 
    ON ac.material_name = m.name 
WHERE EXISTS 
    (SELECT 1 FROM available_material_printmode_config sub   
    WHERE ac.printer_name = sub.printer_name 
     AND ac.printmode_name = sub.print mode_name) 
AND ac.printer_name = '123' AND ac.printmode_name = '2' 

UNION 

SELECT m.name 
FROM material m 
LEFT JOIN available_materials am 
    ON am.material_name = m.name 
WHERE NOT EXISTS 
    (SELECT 1 FROM available_material_printmode_config sub 
    WHERE am.printer_name = sub.printer_name 
     AND sub.printmode_name = '2') 
AND am.printer_name = '123' 
+0

(SELECT 1 FROM available_material_printmode_config子 WHERE am.printer_name = sub.printer_name AND sub.printmode_name = '2')這必須重複? –

+0

聯盟是有道理的。請檢查編輯。 –

+0

即使進行編輯,您的「EXISTS」子查詢也不與外部查詢相關聯,因此它一次不會對整個表進行檢查。請檢查數據以查看SQL是否有效。 – Parfait