2013-04-23 75 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