2013-06-06 23 views
22

我想知道如果列存在,是否可以選擇列的值,否則只選擇null。換句話說,我想「解除」select語句來處理列不存在的情況。如果列存在,請選擇columnValue否則爲空

SELECT uniqueId 
    , columnTwo 
    , /*WHEN columnThree exists THEN columnThree ELSE NULL END*/ AS columnThree 
FROM (subQuery) s 

請注意,我正在鞏固我的數據模型和設計。我希望在接下來的幾周內排除這個邏輯,但是我真的很想超越這個問題,因爲數據模型修復比我現在想要解決的更耗時。

另請注意,我希望能夠在一個查詢中執行此操作。所以我不在尋找像

答案首先檢查您的子查詢上的列。然後修改您的 查詢以適當地處理您的子查詢中的列。

+1

你爲什麼要編寫假設你的數據模型將會是愚蠢的代碼?爲什麼不編寫現在存在的列,並且當ColumnThree在您的數據模型中成爲永久的一等公民時,修復查詢?另外我強烈建議不要告訴人們你不在尋找什麼。你說的限制不可能達到,你需要給出一個比這更好的理由。當你在一個存儲過程中封裝內容時,「在一個查詢中」的意義很小。 –

+0

@AaronBertrand你問了兩個問題,所以我會解決這兩個問題。首先,我的目標是儘快提供高質量的功能。現在,我需要來自'ColumnThree'的值,以使我的功能正常工作。所以我會在存在時使用該列...即使解決方案不夠高雅。 –

+6

@AaronBertrand其次,我感謝你的建議,但恭敬地不同意。我想明確地表達我的要求,以便用戶可以專注於提出解決方案,解決我的問題,而不會浪費時間寫出我知道不令人滿意的答案。我認爲明確說明哪些不會是令人滿意的答案,有助於用戶專注於解決方案的更多價值。 –

回答

18

你不能用一個簡單的SQL語句來做到這一點。除非表中的所有表和列引用都存在,否則SQL查詢將不會編譯。

如果「子查詢」是表引用或視圖,則可以使用動態SQL執行此操作。

在動態SQL,你會做這樣的事情:

declare @sql nvarchar(max) = ' 
SELECT uniqueId, columnTwo, '+ 
    (case when exists (select * 
         from INFORMATION_SCHEMA.COLUMNS 
         where tablename = @TableName and 
          columnname = 'ColumnThree' -- and schema name too, if you like 
        ) 
      then 'ColumnThree' 
      else 'NULL as ColumnThree' 
    end) + ' 
FROM (select * from '[email protected]+' s 
'; 

exec sp_executesql @sql; 

對於實際的子查詢,你可以通過檢查,看是否子查詢返回與列名某事的大致相同的事情。一種方法是運行查詢:select top 0 * into #temp from (<subquery>) s,然後檢查#temp中的列。

+0

我不這麼認爲。出於好奇,我如何用動態SQL來做到這一點? –

+0

您將您的sql語句構建爲一個字符串,然後使用exec命令來執行您建立的字符串。 – liebs19

+0

並從我的動態sql的理解,不會需要兩個查詢? –

12

正如其他人已經建議的那樣,理智的做法是讓查詢符合您的餐桌設計。

雖然有一種相當奇特的方法來實現你想要的(純粹的,不是動態的)SQL。在DBA.SE上發佈了類似的問題:How to select specific rows if a column exists or all rows if a column doesn't,但它更簡單,因爲結果只需要一行和一列。您的問題更復雜,因此查詢更復雜,至少可以說。這裏,瘋狂的做法:

; WITH s AS 
    (subquery)         -- subquery 
SELECT uniqueId 
    , columnTwo 
    , columnThree = 
     (SELECT (SELECT columnThree 
        FROM s AS s2 
        WHERE s2.uniqueId = s.uniqueId 
       ) AS columnThree 
     FROM (SELECT NULL AS columnThree) AS dummy 
     ) 
FROM s ; 

它還假定uniqueId是在結果集的子查詢的唯一。

測試在SQL-Fiddle


,並具有額外的優勢,它允許多個列有一個子查詢一個簡單的方法:

SELECT s.*  
FROM 
    (SELECT NULL AS columnTwo, 
      NULL AS columnThree, 
      NULL AS columnFour 
    ) AS dummy 
    CROSS APPLY 
    (SELECT 
      uniqueId, 
      columnTwo, 
      columnThree, 
      columnFour 
     FROM tableX 
    ) AS s ; 

的問題也被要求在DBA.SE並且已被@Andriy M(也使用CROSS APPLY!)和Michael Ericsson(使用XML)回答:
Why can't I use a CASE statement to see if a column exists and not SELECT from it?

+1

這很酷!有沒有辦法使這個工作與多個列,但沒有更多的聯接? – surjikal

+0

@surjikal看我的編輯! –

+0

感謝您的快速回復!不幸的是,我使用的是SAP Hana,它沒有'CROSS APPLY'。你能想到另一種解決方案嗎?我發現這個https://stackoverflow.com/questions/26020765/sap-hana-alternative-for-cross-apply,但我不知道它是否會工作。 – surjikal

相關問題