2010-05-24 29 views
5

我已經設置了一個視圖,它將幾個表中的所有數據組合在一起。有沒有辦法寫這個,這樣只顯示包含非空數據的列,並且包含所有NULL值的列不包含在內?如何不顯示在視圖中爲NULL的列

添加: 對不起,仍然在學習和工作我的第一個大項目,所以每一天似乎都是一種全新的體驗。我不是很清楚,這部分是因爲我不確定我是否以正確的方式開展事情!客戶是一個學術圖書館,數據庫記錄具體收藏的細節。我提到的觀點是顯示關於某個項目的所有數據,因此它將出版物,副本,作者,出版商,語言等等的表格彙集在一起​​。收藏中的少量項目是論文,因此除標準書目詳細信息之外還有其他細節。我不想要的是一個用戶,如果返回的內容只包含書本,那麼就可以得到所有與論文相關的空白字段,因此紙張表字段全部爲空。所以我想也許會有辦法不顯示這些。有人評論說,這是客戶端應用程序的工作,而不是數據庫本身,所以我可以離開這個,直到我到達項目的這個階段。

+1

如果格式依賴於內容而發生變化,似乎容易誤讀表格數據... – 2010-05-24 15:58:28

+3

因此,如果記錄1的列A有一個值,但記錄2的列A的值爲NULL - 如果該列在視圖? – 2010-05-24 15:59:57

+0

這聽起來像應該在GUI中的邏輯,而不是數據庫。這不符合正確的數據庫檢索合同,因爲佈局可能隨時發生變化。 – cjk 2010-05-24 16:55:18

回答

1
CREATE VIEW dbo.YourView 
AS 
    SELECT (list of fields) 
    FROM dbo.Table1 t1 
    INNER JOIN dbo.Table2 t2 ON t1.ID = t2.FK_ID 
    WHERE t1.SomeColumn IS NOT NULL 
    AND t2.SomeOtherColumn IS NOT NULL 

在視圖定義,可以包括有條件的地方,可以排除有那些爲NULL的某些列行。

更新:你不能真正篩選出 - 定義,在您的視圖定義視圖的一部分列的列表,該列表是固定的,不能動態地改變......

你可以做的是我們ISNULL(column, '')構造用空字符串替換那些NULL。或者你需要在你的顯示前端處理排除 - 不在SQL視圖定義中...

我看到你唯一能做的就是確保只從視圖中選擇那些列你知道是不是NULL:

SELECT (list of non-null fields) FROM dbo.YourView 
WHERE (column1 IS NOT NULL) 

等等 - 但有沒有簡單或神奇的方式選擇不在一個SELECT語句中NULL的所有列...

+0

這是海報的要求嗎? – 2010-05-24 15:59:18

+1

這將過濾掉某些列中包含空值的所有行,這與我認爲海報後面的行有點不同。 – Justin 2010-05-24 16:00:09

+0

一個相當奇怪的請求 - 但你們似乎是正確的....嗯......想不到任何方式來實現.....至少不在SQL級別......或者它可能是隻是一個不幸的話的選擇和OP真的意味着過濾行?我不知道...... – 2010-05-24 16:00:24

0

一般情況下,加WHERE子句給你的查詢,例如

WHERE a IS NOT NULL AND b IS NOT NULL AND c IS NOT NULL 

這裏,bc是你的列名。

如果您將表連接在可能的NULL列上,則使用INNER JOIN,並且不會包含NULL值。

編輯:我可能誤解了 - 上面的過濾出來的行,但你可能會要求過濾列,例如,您有多個列,並且只希望顯示所有要返回的行中包含至少一個空值的列。使用動態SQL提供了一個解決方案,因爲設置列取決於您的數據。

這裏是一個SQL查詢,它構建了包含適當列的另一個SQL查詢。您可以運行此查詢,然後將其結果作爲另一個查詢提交。它假設'pk'是一些總是非空的列,例如一個主鍵 - 這意味着我們可以用逗號前綴其他行名稱。

SELECT CONCAT("SELECT pk" 
    CASE (count(columnA)) WHEN 0 THEN '' ELSE ',columnA' END, 
    CASE (count(columnB)) WHEN 0 THEN '' ELSE ',columnB' END, 
    // etc.. 
    ' FROM (YourQuery) base') 
FROM 
    (YourQuery) As base 

該查詢適用於使用計數(柱) - 聚集函數忽略NULL值,以及用於完全由空值的列,以便返回0。查詢生成器假定YourQuery使用別名來確保不存在重複的列名稱。

雖然你不能把它放到一個視圖中,你可以把它包裝成一個存儲過程,將數據複製到另一個表 - 結果表。您也可以設置一個觸發器,以便在基表發生變化時更新結果表。

3

在sql中沒有辦法做到這一點。

+1

我很想回應這樣,但它取決於數據庫系統。我自認爲可以用臨時表來實現,但邏輯會相當複雜。可以用動態生成的SQL來完成,但是這種方法有更多的注意事項。 – eksortso 2010-05-24 16:07:40

+2

在視圖中不能使用這些技術中的任何一種。 – 2010-05-24 16:14:20

+2

110%正確。 SQL =固定列輸出。 – gbn 2010-05-24 16:33:22

0

如果我們正在閱讀你的問題,那麼在SQL中就沒有辦法做到這一點。視圖的輸出必須是關係 - 以(過)簡化的術語,它必須是矩形的。也就是說,每行必須具有相同數量的列。

如果您可以告訴我們更多關於您的數據的信息,並告訴我們您對輸出結果要做什麼,我們可以提供更積極的建議。

0

您不能在視圖中執行此操作,但您可以在存儲過程中使用動態SQL進行相當簡單的操作。

當然,對於使用數據的客戶來說,擁有一個轉移模式並不一定好,但是如果您的數據非常稀疏並且客戶端了解不同的模式,它可能很有效。

如果你必須有一個視圖,你可以在你的視圖中放置一個「標題」行,你可以在你的循環的第一行檢查客戶端,看看你是否不想打擾你的列網格或什麼的,你可以做這樣的事情:

SELECT * FROM (
    -- This is the view code 
    SELECT 'data' as typ 
      ,int_col 
      ,varchar_col 
    FROM TABLE 

    UNION ALL 

    SELECT 'hdr' as typ 
      -- note that different types have to be handled differently 
      ,CASE WHEN COUNT(int_col) = 0 THEN NULL ELSE 0 END 
      ,CASE WHEN COUNT(varchar_col) = 0 THEN NULL ELSE '' END 
    FROM TABLE 
) AS X 
-- have to get header row first 
ORDER BY typ DESC -- add other sort criteria here 
0

我懷疑這是怎麼回事是最終用戶運行的是水晶報表和抱怨都必須被手動刪除空列。

實際上可以創建一個存儲過程,它可以實時創建一個視圖,而不需要數據列。但是,在使用視圖之前,您必須運行此proc。

這是可以接受的嗎?