2009-11-05 128 views
0

有沒有辦法重寫一個使用CASE WHEN結構來做同樣的事情而不使用CASE WHEN的Transact SQL語句?SQL Server CASE什麼時候不使用CASE什麼時候

我正在使用具有內置查詢設計器和自己的僞SQL的產品。它對我可以用於SQL Server和Oracle的內容有限制。所以我有這個專欄,當底層數據庫是Oracle時,使用DECODE(這是支持的)。但是,我需要使它與SQL Server和CASE WHEN不受支持一起使用。

我想轉換的說法是一樣的東西

Decode (StatusColumn, 'Value 1', 
Decode(Sign(Now()-TargetDateColumn)),1,'Past 
Due', 'Outstanding'), 'Value 2', 
Decode(Sign(Now()-TargetDateColumn)),1,'Past 
Due', 'Outstanding'), 'Value 3', 
Decode(Sign(Now()-TargetDateColumn)),1,'Past 
Due', 'Outstanding'), 'Value 4') 

我有一組有限的T-SQL選項使用和CASE WHEN是不是一種選擇。我確實有IsNull和Coalesce,但我不確定他們是否會幫助我。

不要打擾日期計算,這些都解決了。

我在這裏搜索了CASE WHEN問題,無濟於事。

謝謝!

更新:

我意識到,我應該給更多的細節上的限制的原因,因爲這是一個開發人員的資源,那麼可以斷定,這是一個發展的產物。不是這樣。

我正在使用具有內置查詢設計器和自己的僞SQL的企業軟件產品。它對我可以用於SQL Server和Oracle的內容有限制。基本上,不會破壞內置查詢引擎解析的所有內容都是遊戲。這意味着所有被批准的函數和表達式以及所有數據抽象(與數據庫中的物理表對應的內部對象以及使用該產品創建的其他查詢)以及Oracle SQL或Transact SQL中沒有明確地破壞解析的所有內容。

CASE WHEN不適用於我的原因是它破壞了查詢引擎對僞SQL的解析。

最後,我想嘗試:

  1. 只能使用該產品的查詢 設計師從 的SQL Server數據庫和經過 解析或
  2. 使用一些額外的資源,SQL 查詢設計器完成它。

基於我得到的幾個很好的答案,以下是迄今爲止爲我制定的方法。

Jason DeFontes建議我可以使用數據庫視圖來執行CASE WHEN規則並落入上述#2中。它適用於我,因爲視圖足夠動態,所以我不必對其進行維護(與richartallent的真值表方法相反,我相信它接近Jason的方法)。帕斯卡建議創建一個函數將沿着同樣的路線走,但可能會打破解析。

因此,我創建了一個數據庫視圖,用CASE WHEN完成所有轉換,並將其添加到查詢的SQL中,並將其與現有SQL一起加入,並且工作得很好。我意識到我可能會向數據庫引擎添加開銷,因爲它必須兩次檢索相同的數據集(一個用於查看,一個用於查詢),但這是一個幾乎不成問題的情況之一。

鑑於這種「使用視圖來混淆它」的設計工作對我來說,我不知道這將是更有效的方法:

  • 使用選擇與CASE WHEN;
  • 使用CTE(再次,richardtallent);
  • 使用Union All(HLGEM);
  • 使用子查詢(MisterZimbu);

我仍然會檢查Aramis wyler的建議,因爲它可能會落入上面的#1。

現在,傑森的答案被接受了。考慮到我在視圖中使用了CASE WHEN,或許這個問題的標題最終被錯誤地選擇了。我提高了每個人都提出了一些有助於這一進程的內容。我不知道這是否會影響你的聲譽,但我認爲這是一件好事。

再一次,我要感謝大家的幫助,並且請您編輯關於您不合適的問題(這是我的第一個問題,英語是我的第二語言)。

+0

我很好奇..爲什麼你沒有選擇使用Case When?貴公司是否制定了這樣的政策?!!?不管你有外部授權限制,Case When在SQL Server上肯定受支持。 – 2009-11-05 18:07:36

+0

是的,但查詢工具可能不支持它,將選擇結果限制爲表達式和函數調用。 – pascal 2009-11-05 18:11:19

+0

這是我們正在開發的產品的限制。正如我所提到的那樣,該產品有一個查詢設計器和一個查詢引擎,以及它自己的SQL,可以將其「翻譯」/「充分」到Oracle或SQL Server中。 我懷疑是否支持解碼,因爲它是一個函數,不管我被告知Case-When不是一個函數,而是一個表達式。 我認爲Case-When會由於僞SQL定義而中斷查詢引擎的解析。 – ezingano 2009-11-05 18:14:18

回答

3

您可以將CASE/WHEN邏輯移入視圖,然後讓工具查詢視圖嗎?

+0

你知道嗎?也許我可以! 我正在完成一些其他任務,但會盡快開始嘗試這些建議。到目前爲止,這似乎是一個。 查詢設計器是有限的,但我可以通過一些事情(不是CASE-WHEN,但它打破瞭解析)。的確,我可以嘗試這種方法。 – ezingano 2009-11-05 21:32:58

1

使用CASE WHEN編寫一個執行計算的函數。

+0

現在我不能。如果可能的話,我想嘗試通過使用我在查詢設計器/引擎中提供的解決方案來解決此問題。 在問這個問題之前,我給了它很多思考,因爲我知道它可能會吸引更多的注意力,而不是問題本身。 最終,我認爲它可能對其他人在同一情況下有價值。或者至少是一些關於同樣評估效率的食物。 – ezingano 2009-11-05 18:17:14

4

你有沒有工會可用?也許你可以用where子句中的條件條件爲每個條件寫一個查詢,然後將它們結合在一起。

+0

+1好主意(好吧,除了燒僞SQL工具) – Andomar 2009-11-05 18:30:32

+0

我會試試看。我猜你的答案是我的目標:通過使用基本的SQL而不是函數來處理這個問題。 我將不再回答這個問題,看看是否有其他建議。如果沒有,那麼我會接受你的答案。 謝謝。 – ezingano 2009-11-05 18:51:26

+0

我贊成這個,但UNION確實有兩個缺點:(1)多次訪問井(MSSQL不會優化這個井),和(2)重複的代碼。其中一些可以通過將公共部分移至CTE來緩解,但如果您嘗試避免CASE,則CTE更具有平臺特定性。 – richardtallent 2009-11-05 19:43:48

3

你可以編寫自定義子查詢嗎?也許不是,如果你甚至不必訪問CASE WHEN,但這或許工作太:

select 
    ..., 
    coalesce(c1.value, c2.value, c3.value, ..., <default value>) 
from MyTable 
left join (select <result 1> as value) c1 on <first condition> 
left join (select <result 2> as value) c2 on <second condition> 
left join (select <result 3> as value) c3 on <third condition> 
+0

+1整齊的方法 – Andomar 2009-11-05 19:29:26

+0

我也會試試這個,因爲它可能是查詢引擎限制的一個延伸,但它很容易理解並且更接近我想要做的事情。謝謝! – ezingano 2009-11-05 19:47:15

1

它的醜陋,取決於值的數量你也未必是可行的。但嚴格來說,我認爲像這樣的東西可以用作上述查詢段的翻譯:

從表名Now中選擇'PastDue',其中Now()> TargetDateColumn和(StatusColumn ='Value 1'或StatusColumn ='Value 2'或其中Now()< TargetDateColumn和(StatusColumn ='Value 1'或StatusColumn ='Value 2'或StatusColumn ='Value 3') 聯合選擇'值4'其中NOT(StatusColumn ='Value 1'or StatusColumn ='Value 2'or StatusColumn ='Value 3')

1

我不完全確定我理解你的代碼,但是這應該給你一個不同的方法。

首先,創建一個表:

CREATE TABLE StatusLookup(
    value nvarchar(255), 
    datesign shortint, 
    result varchar(255)); 

現在,真值表填充它(大量重複的邏輯在這裏很明顯,也許這應該是一個CROSS它們之間連接兩個真值表):

INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 1', -1, 'Outstanding') 
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 1', 0, 'Outstanding') 
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 1', 1, 'Past Due') 
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 2', -1, 'Outstanding') 
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 2', 0, 'Outstanding') 
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 2', 1, 'Past Due') 
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 3', -1, 'Outstanding') 
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 3', 0, 'Outstanding') 
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 3', 1, 'Past Due') 

最後,加入並提供一個默認的答案:

SELECT mytable.*, COALESCE(statuslookup.result, 'Value 4') 
FROM 
    mytable LEFT JOIN statuslookup ON 
     statuslookup.value = StatusColumn 
     AND statuslookup.datesign = Sign(Now()-TargetDateColumn) 

一個鍵廣告這種方法的優勢在於它將業務邏輯放在數據表中,而不是代碼中,這通常更易於維護和擴展。

+0

您的建議可能會起作用,因爲我可以在查詢引擎中使用COALESCE。我偏愛真理表,因爲我不想管理它(不是說這不是一個好主意,因爲我以前曾經使用過,但它增加了一個額外的管理層,這對我來說無效特殊情況),但可以完成。謝謝。 – ezingano 2009-11-06 00:48:07

相關問題