2011-06-23 44 views
2

我的數據庫表有以下幾列: A1,A2,A3,A4,A5,A6SQL UPDATE表現不佳

我必須更新這些記錄和移位值留每當我遇到一個空列。目的不是在具有從左開始的值的列之間具有空值。例如,如果:

A1 = NULL , A2 = 1 , A3 = 4, A4 = 5, A5 = 9, A6 = 8 

我有左移這樣的結果將是值:

A1 = 1, A2 = 4 , A3 = 5, A4 = 9, A5 = 8, A6 = NULL 

到目前爲止,我想出了下面的查詢,但它是緩慢的。讓我知道,如果你可以調整查詢,使其更快。還有一件事,如果我在c#中這樣做呢?如果我循環遍歷數據行並更新每一行,會更快嗎?

UPDATE myTable SET 
    A5 = A6, 
    A6 = NULL 
WHERE (A5 IS NULL) AND (NOT A6 IS NULL) 

UPDATE myTable SET 
    A4 = A5, 
    A5 = A6 
WHERE (A4 IS NULL) AND (NOT A5 IS NULL) 

UPDATE myTable SET 
    A3 = A4, 
    A4 = A5, 
    A5 = A6 
WHERE (A3 IS NULL) AND (NOT A4 IS NULL) 

UPDATE myTable SET 
    A2 = A3, 
    A3 = A4, 
    A4 = A5, 
    A5 = A6 
WHERE (A2 IS NULL) AND (NOT A3 IS NULL) 

UPDATE myTable SET 
    A1 = A2, 
    A2 = A3, 
    A3 = A4, 
    A4 = A5, 
    A5 = A6 
WHERE (A1 IS NULL) AND (NOT A2 IS NULL) 
+3

有什麼理由,你不只是在添加這些爲相關的表?通過這樣做違反了常規表單... http://en.wikipedia.org/wiki/First_normal_form#Repeating_groups_across_columns –

+3

確實是一個糟糕的數據模型。 – duffymo

+0

此表中還有其他列,我無法更改設計。我將不得不找到一種方法來在不改變設計的情況下做到這一點。這是一個數據模型不佳的舊系統。 – Sev

回答

0

如果你有過代碼或者數據庫設計沒有控制,我會建議使用觸發器解決這個問題。

設置INSERT,UPDATE觸發器,該觸發器將專門查看剛剛更改的行。這樣您就不會對已經檢查過一致性的數據運行更新聲明。更少的行檢查/更新意味着更好的性能。

通過查看虛擬inserteddeleted表,您可以將其縮小到已觸及的行。

觸發器到位後,觸摸所有現有行(以觸發它們上的觸發器)或運行原始腳本以確保所有內容都處於一致狀態。

0

如果不是這樣,你是否嘗試在所有列上添加覆蓋索引?嘗試按以下方式添加索引。這樣可以更快地找到需要更新的行,覆蓋索引是這樣的,它不必進行書籤查找就可以獲得它需要的下一個值。

A1, A2, A3, A4, A5, A6 
A2, A3, A4, A5, A6 
A3, A4, A5, A6 
A4, A5, A6 
A5, A6 
+0

我不知道如何添加覆蓋索引。 – Sev

+0

不會添加新索引使更新SLOWER成爲可能,因爲這些更新還需要在每個語句中更新?更快地訪問行很好,但索引的更新成本也會增加。 –

2

鑑於[anything] + NULL + [anything]爲空怎麼樣;

declare @t table(A1 int, A2 int, A3 int, A4 int, A5 int, A6 int) 
insert @t values 
    (NULL, 2 , 3, 4, 5, 6), 
    (1, NULL, 3, 4, 5, 6), 
    (1, 2, NULL, 4, 5, 6), 
    (1, 2, 3, NULL, 5, 6), 
    (1, 2, 3, 4, NULL, 6), 
    (1, 2, 3, 4, 5, NULL), 
    (1, 2, 3, 4, 5, 6) 

update @t 
    set A1 = coalesce(A1, A2), 
    A2 = case when A1 + A2    is null then A3 else A2 end, 
    A3 = case when A1 + A2 + A3   is null then A4 else A3 end, 
    A4 = case when A1 + A2 + A3 + A4  is null then A5 else A4 end, 
    A5 = case when A1 + A2 + A3 + A4 + A5 is null then A6 else A5 end, 
    A6 = case when A1 + A2 + A3 + A4 + A5 is null then null else A6 end 
from @t 

select * from @t 


A1 A2 A3 A4 A5 A6 
2 3 4 5 6 NULL 
1 3 4 5 6 NULL 
1 2 4 5 6 NULL 
1 2 3 5 6 NULL 
1 2 3 4 6 NULL 
1 2 3 4 5 NULL 
1 2 3 4 5 6 
+0

如果A1和A2都是NULL,會發生什麼? –

2

如何使用在一份聲明中這樣的合併:

update mytable 
set a1 = coalesce(a1,a2,a3,a4,a5,a6), 
    a2=coalesce(a2,a3,a4,a5,a6), 
    a3=coalesce(a3,a4,a5,a6), 
    a4=coalesce(a4,a5,a6), 
    a5=coalesce(a5,a6) 
+0

沒有這個解決方案不會工作,因爲它複製值 – Sev

+0

你是什麼意思,它不會工作,因爲它複製值?這並不意味着完整的解決方案,只是樣本方法。您可以添加WHERE和/或將其分解爲幾個更專業化的查詢,但我認爲合併會起作用。 – JNappi

+0

讓我今天嘗試一下,我會讓你知道結果。到目前爲止,最有用的答案是你的 – Sev