2012-09-28 70 views
0

我碰到過這樣一個場景,我需要在交叉點從「傳統」到返回一組複雜的計算值的電流。SQL Case語句,在條件使子選擇?

爲了削減長話短說我有這樣的事情......

with someofit as 
(
    select id, col1, col2, col3 from table1 
) 

select someofit.*, 
    case when id < @lastLegacyId then 
    (select ... from table2 where something = id) as 'bla' 
    ,(select ... from table2 where something = id) as 'foo' 
    ,(select ... from table2 where something = id) as 'bar' 
    else 
    (select ... from table3 where something = id) as 'bla' 
    ,(select ... from table3 where something = id) as 'foo' 
    ,(select ... from table3 where something = id) as 'bar' 
    end 
from someofit 

這裏沒有謊言,我不希望經常做着這種情況下,檢查每個子選擇的問題... 但在適用該條件的同時,我需要在相關案例塊中的所有選擇。

有沒有一種更聰明的辦法做到這一點?

如果我是在我會用這樣的一個適當的面向對象的語言......

var common = GetCommonSuff() 

foreach (object item in common) 
{ 
    if(item.id <= lastLegacyId) 
    { 
     AppendLegacyValuesTo(item); 
    } 
    else 
    { 
     AppendCurrentValuesTo(item); 
    } 
} 

我也開始嘗試做2點完整的選擇與UNION ALL但這並不對因工作得很好效率/要評估的行數。

子選項都在尋找其中的一些條件比ID匹配滿足其他在任表2或3,但這些表可能有上百萬行的總他們的行數。

熱膨脹係數是用於2個原因...

首先它拉只從表1中我很感興趣,所以馬上我只是做在每種情況下的子選項的一小部分行。

其次,其返回的共同的東西,在一個單一的查找表1

任何想法?

編輯1:

一些背景的情況......

我有一個表稱爲「進口」(上表1),這代表着我們從文件中的數據導入作業(CSV或類似的)並將記錄拉入數據庫。

然後我有一個叫做「臺階」表,這代表我們通過去處理/清洗規則,每個記錄包含一個存儲過程的名稱和有關規則的一堆其他的東西。

然後有一個連接表,它表示對特定導入「ImportSteps」規則(上文表2 - 對於當前數據),這包含了「的RowsAffected」列和進口ID

所以對於當前工作我SQL是很簡單...

選擇進口 加入了舊的遺留東西importsteps

但是我不得不通過看錶3 123 456 ...表3是保持臺,它包含每個導入的記錄,每行都有一個導入ID和每行包含關鍵值。

上的RowsAffected上表2進口ID x其中一步ID爲y將返回我的價值,新的數據。

對遺留數據我在拿着其中山坳Z =東西

我需要在大約20個進口數據,並將這些數據綁定到我的MVC Web應用程序是「數據網格」(如果要算上行

有什麼區別)

我使用的cte通過一些參數決定了「當前20 im感興趣」這些參數代表開始和結束記錄(按導入id排序)。

我最大的問題是,控股表...它是巨大的..單個作業已知它們自己包含500k +記錄,此表保存多年導入的行,所以我需要在該表上查找我的儘可能快,儘可能少。

編輯2:

實際的解決方案(只suedo代碼)...

-- declare and populate the subset to reduce reads on the big holding table 
declare table @holding (...) 
insert into @holding 
select .. from holding 

select 
    ... common stuff from inner select in "from" below 
    ... bunch of ... 
    case when id < @legacy then (select getNewValue(id, stepid)) 
    else (select x from @holding where id = ID and ...) end as 'bla' 
from 

(
    select ROW_NUMBER() over (order by importid desc) as 'RowNum' 
    , ... 
) as I 
-- this bit handles the paging 
where RowNum >= @StartIndex 
and RowNum < @EndIndex 

我仍然相信我可以更清潔了,但我原來的查詢,看起來像賬單解決方案在執行時間約爲45秒,這是大約7

回答

3

我把它的子查詢必須返回一個標量值,是否正確?這一點很重要,因爲它確保了LEFT JOINs不會增加結果。

;with someofit as 
(
    select id, col1, col2, col3 from table1 
) 

select someofit.*, 
    bla = coalesce(t2.col1, t3.col1), 
    foo = coalesce(t2.col2, t3.col2), 
    bar = coalesce(t2.bar, t3.bar) 
from someofit 
left join table2 t2 on t2.something=someofit.id and somefit.id < @lastLegacyId 
left join table3 t3 on t3.something=someofit.id and somefit.id >= @lastLegacyId 

要小心,我已經使用id >= @lastLegacyId作爲條件的補充,假設該ID不能爲空。如果是這樣,那麼你需要一個IsNull,即somefit.id >= isnull(@lastLegacyId,somefit.id)


你編輯的問題不改變的事實,這是O-O語法的幾乎直譯。

foreach (object item in common) --> "from someofit" 
{ 
    if(item.id <= lastLegacyId)  --> the precondition to the t2 join 
    { 
     AppendLegacyValuesTo(item); --> putting t2.x as first argument of coalesce 
    } 
    else        --> sql would normally join to both tables 
            --> hence we need an explicit complement 
            --> condition as an "else" clause 
    { 
     AppendCurrentValuesTo(item); --> putting t3.x as 2nd argument 
             --> tbh, the order doesn't matter since t2/t3 
             --> are mutually exclusive 
    } 
} 

function AppendCurrentValuesTo  --> the correlation between t2/t3 to someofit.id 

現在,如果你實際上已經嘗試過這樣並且它不能解決你的問題,我想知道它的位置。

+0

這可能會對當前的數據工作,但我不知道舊的遺留物...已經說過...讓我更新問題有點 – War

+0

也可能值得注意的是,ID是主鍵 – War

+0

啊謝謝...這使得更多的敏感e ...我的困難是我的弱sql知識水平...我對我的C#/ linq類型查詢更有信心。 – War

1

假設你知道有兩個表之間沒有衝突的ID,你可以做這樣的事情(DB2語法,因爲這是我所知道的,但它應該是相似的):

with combined_tables as (
    select ... as id, ... as bla, ...as bar, ... as foo from table 2 
    union all 
    select ... as id, ... as bla, ...as bar, ... as foo from table 3 
) 
select someofit.*, combined_ids.bla, combined_ids.foo, combined_ids.bar 
    from someofit 
    join combined_tables on someofit.id = combined_tables.id 

如果您有像重疊ID的情況下,你可以處理combined_tables()部分

+0

這讓我想起我以前的嘗試在這個查詢中...... union聲明導致查詢需要大約30秒的時間來運行我的樣本數據(實時數據的一個子集)......我看不到它使得查詢的效率足夠高,但是一個間隙的想法如果我可以將2個「非常見」數據集以某種方式加入臨時表或其他東西,然後加入到我的cte – War

+0

@Wardy中,這一切都取決於您的數據,特別是哪些表更大。如果table1比table2和table3大,這可能是一個有效的解決方案。但是,如果table2和table3比table1大,則會增加額外的開銷。 – dan1111

+0

你當然是對的,關鍵是桌子的大小,而不是我拉動最大桌子子集的推理。其他表格預計不會很長。我想我的問題是真的......如何以最快的方式反覆查詢那個大型保留表的一個子集......當然,答案是...拉一個子集,然後對其進行連接或子查詢,而不是實際表。歡呼的建議:) – War