2015-08-09 107 views
2

檢查最小和最大的ID後,我需要從下表#a尋找失蹤的id:的我需要找到從表中缺少ID從另一個表

id |SEQ|Text 
1 |1 |AA 
1 |3 |CC 
1 |4 |DD 
1 |5 |EE 
1 |6 |FF 
1 |7 |GG 
1 |8 |HH 
1 |10 |JJ 
2 |1 |KK 
2 |2 |LL 
2 |3 |MM 
2 |4 |NN 
2 |6 |PP 
2 |7 |QQ 
3 |1 |TT 
3 |4 |ZZ 
3 |5 |XX 

MAX和MIN SEQ表#a存儲在另一個表#b:下面

id| mn| mx 
1 | 1 | 12 
2 | 1 | 9 
3 | 1 | 5 

我的查詢給予正確的輸出,但執行是昂貴的。有沒有解決這個問題的另一種方法?

with cte 
as 
(
    select id, mn, mx 
    from #b 

    union all 

    select id, mn, mx -1 
    from cte 
    where mx-1 > 0 
) 
select 
    cte.id, cte.mx 
from 
    cte 
    left join #a on cte.id = #a.id and cte.mx = #a.seq 
where 
    #a.seq is null 
order by cte.id, cte.mx 

主要有在此查詢2個問題:

  1. 查詢運行速度非常慢。上述記錄僅僅是一個例子。在真實的數據庫中,我有50,000行。 enter image description here

  2. 我試着瞭解檢測打嗝的執行計劃。但是我無法理解它的某些部分,我在Red中已經強調了這一點。

如果有人能幫助我,這將是一件好事。我被卡住了。

回答

2

您使用遞歸CTE到generate a set of numbers。這樣做效率相當低(參見生成50K號碼的圖表here)。我建議在數據庫中有一個持久的數字表。我個人有一個表Numbers與100K行與一列Number,這是一個主鍵,它具有從1到100,000的整數。

一旦你這樣的表,查詢簡化爲這樣的:

SELECT 
    #b.id, #b.mx 
FROM 
    #b 
    INNER JOIN Numbers ON 
     #b.mx >= Numbers.Number AND 
     #b.mn <= Numbers.Number -- use this clause if mn can be more than 1 
    LEFT JOIN #a ON 
     #a.id = #b.id AND 
     #a.seq = Numbers.Number 
WHERE 
    #a.seq IS NULL 
ORDER BY #b.id, #b.mx 

而且,不用說,你必須確保你在id#b有指標,再加上#a指數在(id, seq)

+0

謝謝你。它是從sys.all_objects生成數字的好方法。我將在明天上班時測試它的表現。但我確信這種方法會提高查詢性能。再次感謝你的時間 – sam

+0

@sam,如果你有一個持久的數字表,它將有一個主鍵(唯一索引)。如果你想要表現,有一個索引是很重要的。 –

0

CTE只是語法和最有可能得到多次評估
物化爲CTE輸出到#TEMP並加入到#TEMP

1

兩件事情,我想起有:

  • 使用數字/計數表。通過創建一個普通表或使用CTE創建一個虛擬表。用它來查找不存在的數字。

  • 如果不是很多丟失號碼的,你可以使用與ROW_NUMBER()一招地發現,沒有任何間隙的是這樣的數字範圍:

    select id, min(seq), max(seq) 
    from (
        select 
        id, 
        seq, 
        seq - row_number() over (partition by id order by SEQ asc) GRP 
        from 
        table1 
    ) X group by id, GRP 
    order by 1 
    

當您找到存在的數字範圍後,這當然需要更多的處理。

+0

請問請詳細說明row_number如何幫助您查找範圍?我沒有看到它可以幫助http://數據。stackexchange.com/stackoverflow/query/edit/345587 –

+0

@RoyiNamir你正在使用a進行分區,所以你的行號總是1,刪除它。 –

+0

謝謝。你是對的。 PS如果'a'不是以'1'開頭的話?我怎樣才能_align_ row_number偏移量? –