2013-04-23 77 views
1

我曾考虑过使用CASE语句清理一些,现在它运行大约10秒钟。想要压缩这一点以及冗余代码调用。想知道是否有比CASE更好的方法。这可以清理或浓缩任何?

有3个独立的代码块。除了分配颜色外,每个块几乎完全相同,取决​​于队列中有多少天。

绿色小于1天的任何东西。 黄色的东西大于1天但少于3天。 红色大于3天的任何东西。

select m.number, 'status1', 'Green', datediff(day, (select max(datechanged) from statushistory where accountid = m.number), getdate()) 
from master m with (nolock) 
inner join customer c with (nolock) on m.customer = c.customer 
where m.status = 'status1' 
and datediff(day, (select max(sh.datechanged) from statushistory sh where accountid = m.number), getdate()) <= 1 
and qlevel < 998 
and (m.desk not like 'ATY%') 
and (isnull(m.link,0) = 0 or m.linkdriver = 1) 
and m.desk not in ('param1','param2','param3','param4','param5','param6','param7','param8','param9','param10','param11','param12') 

select m.number, 'status1', 'Yellow', datediff(day, (select max(datechanged) from statushistory where accountid = m.number), getdate()) 
from master m with (nolock) 
inner join customer c with (nolock) on m.customer = c.customer 
where m.status = 'status1' 
and datediff(day, (select max(sh.datechanged) from statushistory sh where accountid = m.number), getdate()) between 1 and 2 
and qlevel < 998 
and (m.desk not like 'ATY%') 
and (isnull(m.link,0) = 0 or m.linkdriver = 1) 
and m.desk not in ('param1','param2','param3','param4','param5','param6','param7','param8','param9','param10','param11','param12') 

select m.number, 'status1', 'Red', datediff(day, (select max(datechanged) from statushistory where accountid = m.number), getdate()) 
from master m with (nolock) 
inner join customer c with (nolock) on m.customer = c.customer 
where m.status = 'status1' 
and datediff(day, (select max(sh.datechanged) from statushistory sh where accountid = m.number), getdate()) >= 3 
and qlevel < 998 
and (m.desk not like 'ATY%') 
and (isnull(m.link,0) = 0 or m.linkdriver = 1) 
and m.desk not in ('param1','param2','param3','param4','param5','param6','param7','param8','param9','param10','param11','param12') 

编辑#1

select m.number, 'status1', 
CASE 
    WHEN datediff(day, (select max(sh.datechanged) from statushistory sh where accountid = m.number), getdate()) <= 1 THEN 'Green' 
    WHEN datediff(day, (select max(sh.datechanged) from statushistory sh where accountid = m.number), getdate()) between 1 and 3 THEN 'Yellow' 
    WHEN datediff(day, (select max(sh.datechanged) from statushistory sh where accountid = m.number), getdate()) > 3 THEN 'Red' 
END 
, datediff(day, (select max(datechanged) from statushistory where accountid = m.number), getdate()) 
from master m with (nolock) 
inner join customer c with (nolock) on m.customer = c.customer 
where m.status = 'status1' 
--and datediff(day, (select max(sh.datechanged) from statushistory sh where accountid = m.number), getdate()) <= 1 
and qlevel < 998 
and (m.desk not like 'ATY%') 
and (isnull(m.link,0) = 0 or m.linkdriver = 1) 
and m.desk not in ('param','param','param','param','param','param','param','param','param','param','param','param') 
+1

我认为CASE语句是要走的路。 – zimdanen 2013-04-23 20:25:13

+0

我会使用公共表格表达式(CTE)请参阅http://msdn.microsoft.com/en-us/library/ms175972.aspx – 3dd 2013-04-23 20:30:08

+0

@ 3dd我编辑了我的CASE版本的原始帖子。你知道你如何将它转换成CTE吗?这条语句的结果将需要插入到表中。 – 2013-04-23 20:34:48

回答

1
with cte as (
    select 
     m.number, 
     m.status, 
     days = datediff(day, (select max(datechanged) from statushistory where accountid = m.number), getdate()) 
    from 
     master m with (nolock) 
     inner join customer c with (nolock) on m.customer = c.customer 
    where 
     m.status = 'status1' 
     and d between 1 and 2 
     and qlevel < 998 
     and (m.desk not like 'ATY%') 
     and (isnull(m.link,0) = 0 or m.linkdriver = 1) 
     and m.desk not in ('param1','param2','param3','param4','param5','param6','param7','param8','param9','param10','param11','param12') 

), colorThresholds as (
    select color = 'Green', minDays = null, maxDays = 1 union 
    select 'Yellow', 2, 3 union 
    select 'Red', 4, null 
) 

/* now apply the color thresholds */ 
select 
    c.*, 
    ct.color 
from 
    cte c 
    /* outer join in case the thresholds don't cover all ranges */ 
    left outer join colorThresholds ct on 
     (ct.minDays is null or c.days >= ct.minDays) 
     and (ct.maxDays is null or c.days <= ct.maxDays) 
+0

感谢dotjoe,我不太熟悉CTE。我实际上必须评论1和2之间的差异,因为它可以工作。但即使有这样的评论,它似乎显示我正在寻找的确切结果。你知道CTE对CASE变体有什么优势吗? – 2013-04-23 21:28:08

+0

@JamesWilson cte的基本上是一个易于(重新)使用的子查询。其中一个好处是,datediff功能只在一个地方。看看你如何为每个案例陈述复制它?这使得维护起来很麻烦。 – dotjoe 2013-04-23 21:39:37

+0

@JamesWilson只要colorThresholds cte,这可以很容易地被你的CASE语句取代。当你想把查询分解成小块时,CTE很适合使用。当计算/计算列将在其他地方(如where子句,连接或其他列的一部分)需要时,我喜欢使用它们。尽量避免重复的代码。 – dotjoe 2013-04-23 21:42:34