2015-06-22 35 views
1

我正在努力解決「羣島和差距」問題。這是針對SQL Server 2008/2012(我們兩個都有數據庫)。SQL Server:羣島和差距

我有一個表跟蹤「可用」串行 - #的通道出口;即巴士通行證,入場券,迪斯尼樂園門票等。這些序列號是VARCHAR,可以是數字和字符的任意組合......任何長度,直到定義列的最大值......其中是VARCHAR(30)。而這正是我非常努力地處理VIEW的語法/設計的地方。

表(IM_SER),它包含所有的這些數據都有一個主鍵包括:

ITEM_NO...VARCHAR(20), 
SERIAL_NO...VARCHAR(30) 

在許多情況下尤其...與不同類型的的「總線傳遞」涉及那些Serial-#可以很容易地跟蹤千位數。需要什麼......是SQL Server中的一個簡單視圖...它只輸出可用序列的連續範圍 - #...直到找到GAP(即序列中的BREAK)。例如,假設我們有以下系列 - 手#的,對於給定本期特價貨品#:

123 
124 
125 
139 
140 
ABC123 
ABC124 
ABC126 
XYZ240003 
XYY240004 

在我上面的例子中,輸出將顯示如下:

123 -to- 125 
139 -to- 140 
ABC123 -to- ABC124 
ABC126 -to- ABC126 
XYZ240003 to XYZ240004 

總共有10個串行 - #... ...但由於我們輸出連續範圍 ...只需要5行輸出。這有意義嗎?請讓我知道...並再次感謝您!...馬克

+0

序列號的不同格式將是一個位的問題。在你的例子中,你會如何處理ABC1244? – TheMadDBA

+0

你可以將你的號碼分成2部分,字符串部分(空,ABC或XYZ)+然後數字?這樣你可以單獨處理這些字段,併爲該數字進行所需的間隔和孤島計算。 –

+0

嗨TheMadDBA。如果我們有一個記錄,考慮到上面的例子,使用「ABCD1244」,那麼我們必須有六行輸出,因爲你會是正確的,因爲它不會落入一個連續的範圍。 嗨JamesZ。我沒有任何線索如何做到這一點。這就是爲什麼我需要語法幫助:-)謝謝!Mark – user3411749

回答

0

這應該讓你開始...有趣的部分將確定是否有差距或不。你必須以不同的方式處理每一個串行格式一點點,以確定是否有縫隙或不...

select x.item_no,x.s_format,x.s_length,x.serial_no, 
LAG(x.serial_no) OVER (PARTITION BY x.item_no,x.s_format,x.s_length 
ORDER BY x.item_no,x.s_format,x.s_length,x.serial_no) PreviousValue, 
LEAD(x.serial_no) OVER (PARTITION BY x.item_no,x.s_format,x.s_length 
ORDER BY x.item_no,x.s_format,x.s_length,x.serial_no) NextValue 
from 
(
select item_no,serial_no, 
len(serial_no) as S_LENGTH, 
case 
WHEN PATINDEX('%[0-9]%',serial_no) > 0 AND 
     PATINDEX('%[a-z]%',serial_no) = 0 THEN 'NUMERIC' 
WHEN PATINDEX('%[0-9]%',serial_no) > 0 AND 
     PATINDEX('%[a-z]%',serial_no) > 0 THEN 'ALPHANUMERIC' 
ELSE 'ALPHA'  
end as S_FORMAT 
from table1) x 
order by item_no,s_format,s_length,serial_no 

http://sqlfiddle.com/#!3/5636e2/7

| item_no |  s_format | s_length | serial_no | PreviousValue | NextValue | 
|---------|--------------|----------|-----------|---------------|-----------| 
|  1 |  ALPHA |  4 |  ABCD |  (null) |  ABCF | 
|  1 |  ALPHA |  4 |  ABCF |   ABCD | (null) | 
|  1 | ALPHANUMERIC |  6 | ABC123 |  (null) | ABC124 | 
|  1 | ALPHANUMERIC |  6 | ABC124 |  ABC123 | ABC126 | 
|  1 | ALPHANUMERIC |  6 | ABC126 |  ABC124 | (null) | 
|  1 | ALPHANUMERIC |  9 | XYY240004 |  (null) | XYZ240003 | 
|  1 | ALPHANUMERIC |  9 | XYZ240003 |  XYY240004 | (null) | 
|  1 |  NUMERIC |  3 |  123 |  (null) |  124 | 
|  1 |  NUMERIC |  3 |  124 |   123 |  125 | 
|  1 |  NUMERIC |  3 |  125 |   124 |  139 | 
|  1 |  NUMERIC |  3 |  139 |   125 |  140 | 
|  1 |  NUMERIC |  3 |  140 |   139 | (null) | 
+0

Hi TheMadDBA。 OK,所以我檢查了你的代碼,稍微修改了一下,這樣Serial#就全部按順序排列,如下: order by item_no,s_format,s_length,serial_no 現在,使用你的SQLFiddle,他們都是「按順序」可以這麼說,這很好。 我不明白的是,在「範圍」中輸出它的語法是什麼?有沒有可以在這裏完成的某種類型的組合,還是我錯過了這條船?請讓我知道...我很困惑...謝謝!... Mark – user3411749

+0

好吧,我沒有時間爲您寫一切,但是......您必須添加邏輯來確定序列號是否按順序輸出,並輸出另一列(使用上一個和下一個值列進行比較)。然後,您可以根據需要包裝另一個選擇以進行過濾和/或分組。 – TheMadDBA