2013-03-22 55 views
0

以下是我的:如何基于一组分层规则来执行复杂的SQL选择?

T1是来自复杂SQL的ID和总计的很大选择。 TA,PF和BL是用于保存不同地址信息的3个不同表格。

为了得到正确的地址在T1每个ID,有一组3个层次规律可循:

TA是第一个地址表与T1.ID.检查行的存在如果TA中存在一行,则获取地址并忽略检查表PF和BL。

PF是第2个地址表,用于检查我是否从TA返回任何没有返回的T1.ID.如果PF中存在一行,则获取地址并忽略检查表BL。

BL是第3个地址表,用于检查是否从PF返回任何返回的T1.ID,如果BL中存在一行,则获取地址。

现在我有类似以下的代码,它运行很长时间,即使单独使用UNION也不会!我怎样才能以有效的方式编写这个逻辑?请帮忙!

select T1.ID, TA.ADDRESS,T1.TOTALS 
from T1, TA 
where T1.ID = TA.ID and TA.ADDRESS like "1" 

UNION 

select T1.ID, PF.ADDRESS,T1.TOTALS 
from T1, PF 
where T1.ID = PF.ID and PF.ADDRESS like "2" 
and not exists(select 1 
       from TA 
       where TA.ID = T1.ID 
       and TA.ADDRESS like "1") 
UNION 

select T1.ID, BL.ADDRESS, T1.TOTALS 
from T1, BL 
where T1.ID = BL.ID and BL.ADDRESS like "3" 
and not exists(select 1 
       from TA 
       where TA.ID = T1.ID 
       and TA.ADDRESS like "1") 
and not exists(select 1 
       from PF 
       where PF.ID = T1.ID 
       and PF.ADDRESS like "2") 
+2

Hi @tweetybird。您可能已经注意到我已将您的帖子格式化。 Stack Overflow的要点是如果你想让代码看起来像代码一样,在它前面至少放4个空格。就你的问题而言,鉴于你在叙述中经常看到“if”这个词,你是否熟悉sql函数coalesce()?多数数据库都支持它。你的可能,但很难说,因为你没有识别它(提示提示) – 2013-03-22 02:30:21

回答

0

首先,将ADDRESS like "1"更改为ADDRESS = "1"。在这种情况下,数据库引擎将能够使用ADDRESS上的索引(如果存在)。

其次,你可以摆脱not exist如果你这样做:

select T1.ID, TA.ADDRESS,T1.TOTALS, TA.ADDRESS 
from T1, TA 
where T1.ID = TA.ID and TA.ADDRESS like "1" 

UNION 

select T1.ID, PF.ADDRESS,T1.TOTALS, PF.ADDRESS 
from T1, PF 
where T1.ID = PF.ID and PF.ADDRESS like "2" 

UNION 

select T1.ID, BL.ADDRESS, T1.TOTALS, BL.ADDRESS 
from T1, BL 
where T1.ID = BL.ID and BL.ADDRESS like "3" 

ORDER BY 4 

正如你可以在上面查询看到我已经包括ADDRESS到所选列的列表,并通过此列排序。我从查询中删除了not exist。这意味着将选择所有地址,按优先级排序

现在,您有两种选择:使用应用程序只抓取第一行,忽略其他,或者如果无法修改应用程序代码,那么你需要使用TOP(用于SQL Server),LIMIT(用于MySql),ROW_NUM(用于Oracle)技术来获取前n行。你没有标记你使用的RDBMS,所以,请找出你自己

+0

谢谢@Dan Bracuk。由于截止日期我刚刚结果,但我会在稍后尝试您的方法。 – tweetybird 2013-03-23 00:35:13