关于加入的问题

时间:2009-10-20 17:12:23

标签: sql mysql

我需要做这样的事情来填写零件表:

SELECT (CASE t1.part IS NULL THEN t2.part ELSE t1.part END) AS partno,
       t3.desc    
FROM t1 
LEFT JOIN join t2 ON [certain condition]
LEFT JOIN t3 ON t1.part = t3.part 
             OR t2.part = t3.part

...所以这将从t2中选择partno的值,如果该部分在t1中为null,那么我需要从t3获取描述但是当我运行它时需要永远而且永远不会返回结果,怎么能我这样做得更快?如果我遗漏了一些细节,请询问。

这是表格

alt text http://img15.imageshack.us/img15/3878/74385879.png

这是实际程序

DELIMITER $$

DROP PROCEDURE IF EXISTS `getMonthDetail` $$
CREATE DEFINER=`root`@`%` PROCEDURE `getMonthDetail`(fechai Date, wid int)
BEGIN

select distinct
ins.inventoryinid,
(
select group_concat(concat(documents.documentname,': ', inventoryin_documents.documentno))
from inventoryin_documents
left join documents on documents.documentid=inventoryin_documents.documentid
where inventoryin_documents.inventoryinid = docin.inventoryinid
group by inventoryin_documents.inventoryinid
)as docin,
trace.inventoryoutid,
(
select group_concat(concat(documents.documentname,': ', inventoryout_documents.documentno))
from inventoryout_documents
left join documents on documents.documentid=inventoryout_documents.documentid
where inventoryout_documents.inventoryoutid = docout.inventoryoutid
group by inventoryout_documents.inventoryoutid
) as docout,
outs.inventoryoutdate,
(case when trace.partnumberp is null then indetails.partnumberp else trace.partnumberp end) as nopart,
p.descriptionsmall,
trace.quantity


from
inventoryin as ins
left join inventoryinouttrace as trace on trace.inventoryinid = ins.inventoryinid
left join inventoryin_documents as docin on docin.inventoryinid = ins.inventoryinid
left join inventoryout_documents as docout on docout.inventoryoutid = trace.inventoryoutid
left join inventoryout as outs on outs.inventoryoutid = trace.inventoryoutid
left join inventoryindetails indetails on ins.inventoryinid = indetails.inventoryinid
left join product as p on trace.partnumberp=p.partnumberp

where
((ins.inventorydate > fechai+0 and ins.inventorydate < fechai+100)
or (outs.inventoryoutdate > fechai+0 and outs.inventoryoutdate < fechai+100));

END $$

DELIMITER ;

当我在查询浏览器中点击“解释”按钮时,它会返回错误...

5 个答案:

答案 0 :(得分:1)

OR子句运行缓慢,您应该考虑用UNION替换它们,UNION仍会使用您在t1,t2和t3表中可能有的任何INDEXES:

SELECT IFNULL(t1.part, t2.part) AS partno, t3.desc
FROM t1
LEFT JOIN t2 ON (condition here)
LEFT JOIN t3 ON (t1.part = t3.part)

UNION DISTINCT

SELECT IFNULL(t1.part, t2.part) AS partno, t3.desc
FROM t1
LEFT JOIN t2 ON (condition here)
LEFT JOIN t3 ON (t2.part = t3.part)

此外,您的CASE()函数与我简化的IFNULL()函数非常相似,最终使用临时表。这在使用这些功能时是不可避免的。

答案 1 :(得分:1)

尝试:

   SELECT COALESCE(t1.part, t2.part) AS partno,
          COALESCE(t3.desc, t4.desc)    
     FROM t1 
LEFT JOIN join t2 ON [certain condition]
LEFT JOIN t3 ON t3.part = t1.part
LEFT JOIN t3 AS t4 ON t4.part = t1.part

OR因性能不佳而臭名昭着。

答案 2 :(得分:0)

告诉我们数据的实际结构,请向我们展示查询的EXPLAIN,以便我们了解为什么它运行缓慢!

只有一个猜测:右边的coumns上有索引吗?

答案 3 :(得分:0)

您的特定条件应为t2.id=t1.id并且WHERE语句中包含更多where子句。

您可能希望将其简化为只有两个select语句,并且首先查看它是否很慢。

您可能错过了一个有用的索引。

一旦两个选择都没问题,那么您可以将case命令添加到sql中,看看发生了什么,但不要更改查询中的任何其他内容。

然后,您可以提供查询和时间,这将有助于人们给出更好的答案。

答案 4 :(得分:0)

显而易见的出血:我想你已经为你在连接中使用的字段建立了索引?