2014-09-27 145 views
0

我有哪裏範圍存儲SQL查找範圍

Fileno|fileFrom|fileTo 
Abc |1  |20 
Abc |21  |50 
DGM |51  |60 

我顯示此記錄用戶使用gridview的asp.net

用戶輸入他已經完成印刷範圍的SQL表差距

例如; 31至40

現在我想告訴用戶他再次訪問該頁面時 像

Fileno|fileFrom|fileTo 
Abc |1  |30 
Abc |41  |50 
DGM |51  |60 

如何使用SQL服務器來達到相同的結果待定的範圍?

+1

只要是明確的:如果用戶輸入A..B,並沒有爲範圍X..Y的記錄(用X <=A & Y> = B),要更換這個紀錄一個用於範圍X..A-1(如果X <= A-1)和B + 1..Y(如果Y> = B + 1)? – 2014-09-27 12:55:47

+0

對不起!我已編輯輸出 – 2014-09-27 12:59:40

+0

您是否考慮存儲用戶已完成打印的範圍? – 2014-09-27 13:23:07

回答

0

您應該更新在末端部分重疊的範圍,刪除完全覆蓋的範圍並拆分中間覆蓋的範圍。

-- partial overlap at the begining 
update table ranges 
set filefrom = @to + 1 
where fileno = @fileno and @from <= filefrom and @to < fileto 

-- partial overlap at the end 
update table ranges 
set fileto = @from - 1 
where fileno = @fileno and @from > filefrom and @to >= fileto 

-- complete overlap 
delete from ranges 
where fileno = @fileno and @from <= filefrom and @to >= fileto 

-- split 
insert into ranges 
select fileno, filefrom, @from - 1 
from ranges 
where fileno = @fileno and @from > filefrom and @to < fileto 

insert into ranges 
select fileno, @to + 1, fileto 
from ranges 
where fileno = @fileno and @from > filefrom and @to < fileto 

delete from ranges 
where fileno = @fileno and @from > filefrom and @to < fileto 
+0

我想到了。我們需要在每個插頁上執行六個命令。所以這會影響表現,所以我有第二個想法。但這是最好的選擇嗎? – 2014-09-28 04:18:56

+0

如果您的原始範圍不重疊,則分割範圍的情況會排除其他範圍。你可以查詢範圍內的字段進行拆分,如果沒有前三個字段,則執行拆分。 – 1010 2014-09-29 16:13:24

1

當存儲範圍

當你想從一組可能重疊 範圍刪除範圍,需要多個語句。

 
To be printed   |-------| 
Actually printed  |---| 

例如,當用戶打印範圍的「中間」塊,留下 開始和結束區塊未打印的,你不能更新與 一個SQL語句中的數據。您必須更新原始行,並且 會插入一個新行,或者您必須刪除原始行並插入兩行 行。

事實上,無法預測是否需要更新語句,多個更新語句或更新和插入語句的組合是紅色標記。

在任何情況下,每個用戶都必須在該表上選擇,插入,更新和刪除 特權。您是否可以忍受這是依賴於應用程序的 ,但這是另一個紅旗。

這些紅旗並不意味着「永遠不要這樣做」。他們意思是停下來,坐在你的手上,並說,「等一下......」

當存儲個別事實

這往往簡單存儲個別事實,而不是他們的 範圍。有幾種不同的方法:a)僅存儲需要打印的 ; b)存儲需要打印的內容和 已打印的內容。

如果您只存儲需要打印的內容,記錄什麼已被 打印只需要選擇和刪除權限。

如果使用兩個表 - 存儲在一個「要打印」,並在其他「已經 印」 - 用戶需要只選擇特權「是 印有」(選擇,如果插入特權用戶可以添加要打印的東西 ),並在「已打印」上選擇並插入權限。

例如,如果您只存儲需要打印的內容,請使用此表啓動 。

-- Does *not* assume that to_print is unique. 
create table to_be_printed (
    file_no varchar(10) not null, 
    to_print integer not null 
    check (to_print > 0), 
    primary key (file_no, to_print) 
); 

create index on to_be_printed (to_print); 

insert into to_be_printed values 
('Abc', 1), ('Abc', 2), ('Abc', 3), ('Abc', 4), ('Abc', 5), 
('Abc', 6), ('Abc', 7), ('Abc', 8), ('Abc', 9), ('Abc', 10), 
('Abc', 11), ('Abc', 12), ('Abc', 13), ('Abc', 14), ('Abc', 15), 
('Abc', 16), ('Abc', 17), ('Abc', 18), ('Abc', 19), ('Abc', 20), 
('Abc', 21), ('Abc', 22), ('Abc', 23), ('Abc', 24), ('Abc', 25), 
('Abc', 26), ('Abc', 27), ('Abc', 28), ('Abc', 29), ('Abc', 30), 
('Abc', 31), ('Abc', 32), ('Abc', 33), ('Abc', 34), ('Abc', 35), 
('Abc', 36), ('Abc', 37), ('Abc', 38), ('Abc', 39), ('Abc', 40), 
('Abc', 41), ('Abc', 42), ('Abc', 43), ('Abc', 44), ('Abc', 45), 
('Abc', 46), ('Abc', 47), ('Abc', 48), ('Abc', 49), ('Abc', 50), 
('DGM', 51), ('DGM', 52), ('DGM', 53), ('DGM', 54), ('DGM', 55), 
('DGM', 56), ('DGM', 57), ('DGM', 58), ('DGM', 59), ('DGM', 60); 

爲了指示用戶已經通過31 40印刷號碼,從該表只是刪除 那些行。

delete from to_be_printed 
where to_print between 31 and 40; 

友好的呈現

存儲單個事實並不完全解決問題。您 可能仍然需要向用戶提供數據作爲每個 文件編號的範圍。這類問題的搜索條件是「sql間隙和 島嶼」。

select file_no, min(to_print) as range_start, max(to_print) as range_end 
from 
    (select file_no 
      , to_print 
      , to_print - row_number() over 
          (partition by file_no order by to_print) as grouping 
    from to_be_printed 
    ) as d 
group by file_no, grouping 
order by file_no, range_start; 
 
file_no range_start range_end 
-- 
Abc  1   30 
Abc  41   50 
DGM  51   60