2012-10-03 41 views
3

假設我有如下表:羅馬數字頁碼數據庫

create table Section (
    id integer not null primary key, 
    book_id integer not null foreign key references Book (id), 
    title varchar(100) not null, 
    page_start varchar(10) not null, 
    page_end varchar(10) not null 
    ... remaining fields ... 
) 

注意,起始頁和結束頁字段是VARCHAR處理。這樣我就可以從通常用羅馬數字的序言中包含頁碼。

我的問題是:什麼是修改此表,寫一個應用程序,這樣的有效途徑:

  • 我可以得到正確的開始和結束頁面,最理想的是採用SQL
  • 我可以在部分排序計算頁數段的長度
  • 我能確定給定的頁碼(例如,「十八」或475)是否在給定區間內

在牢記FOLL欠條件/事實:

  • 我不希望用戶必須輸入任何附加信息。例如,他們不應該計算前綴的阿拉伯語等值並輸入。
  • 無論準備書籍的預編號是什麼樣的規則都可以完全遵循(例如,所有的頁碼都將被輸入正確的羅馬或阿拉伯文格式)
  • 我可以添加任何額外的字段,如果需要,甚至可以添加一個單獨的表格
  • 這是一個網絡應用程序,所以我可以對數據進行預處理或後處理在數據庫中插入或顯示數據之前
  • 可以即時添加或刪除部分,例如可能有一個介紹部分,然後再添加另一部分。分頁和排序應該對該書中的所有章節保持正確。

我可能最終會在不同的平臺上以幾種不同的語言實現這一點,所以代碼不可知的僞代碼將是首選。

澄清

因爲我處理成千上萬的記錄,我不能只是通過所有這些循環編程方式做這樣的事情整理。所以一些工作需要在數據庫端進行。

使用查找表的NJK的想法,我們有這樣的事:

SELECT id, book_id, title, page_start, page_end, 
    COALESCE(RN_Lookup_End.value - RN_Lookup_Start.value + 1, CAST(page_end AS integer)-CAST(page_start AS integer) + 1) as number_of_pages 
FROM 
    Section 
    LEFT JOIN RN_Lookup AS RN_Lookup_Start ON Section.page_start=RN_Lookup_Start.key 
    LEFT JOIN RN_Lookup AS RN_Lookup_End ON Section.page_end=RN_Lookup_End.key 
ORDER BY 
    book_id, 
    CASE WHEN RN_Lookup_Start.value IS NOT NULL 
    THEN -1 
    ELSE 0 
    END, -- roman page numbers come before normal page numbers 
    COALESCE(RN_Lookup_Start.value, page_start), COALESCE(RN_Lookup_End.value, page_end) 

如果我通過網頁數量排序的所有書籍要循環。這看起來不錯嗎?

在它的思考,我不知道如果進行以下更改表會更好:

create table Section (
    id integer not null primary key, 
    book_id integer not null foreign key references Book (id), 
    title varchar(100) not null, 
    page_start integer not null, 
    page_end integer not null, 
    is_front_matter bit default 0, 
    page_start_label varchar(10) null, 
    page_end_label varchar(10) null 
    ... remaining fields ... 
) 

以上查詢是這樣的:

SELECT id, book_id, title, 
    COALESCE(page_start_label, CAST(page_start as varchar)) as page_start, 
    COALESCE(page_end_label, CAST(page_end as varchar)) as page_end, 
    (page_end - page_start + 1) as number_of_pages 
FROM 
    Section 
ORDER BY 
    book_id, is_front_matter DESC, page_start, page_end 

那麼我就得在插入和更新時,將page_start_labelpage_end_label的值從羅馬轉換爲阿拉伯語。這兩個額外的整數加上位意味着每個記錄有超過8個字節的額外存儲空間,但大多數記錄離開page_start_labelpage_end_label空白我可能實際上保存空間!

這聽起來像一個合理的解決方案嗎?或者我錯過了一個潛在的陷阱/缺點?

+1

*這是一個Web應用程序,這樣我就可以插入或顯示數據*之前,已在數據庫中的數據做預處理或-post-處理。然後,我會建議你在應用程序層中執行此操作,而不是SQL。 – RedFilter

+0

將頁碼存儲爲整數並將其轉換爲PHP中的羅馬數字。在某處添加一個字段(section?book?),指示最終用戶應該看到的格式 – NullUserException

+1

我將創建一個查詢表,該查詢表引用實際頁碼至圖紙編號。 – Kermit

回答

1

雖然我通常會離開表示細節表現層,我同意在這種情況下@njk。

由於您將羅馬數字作爲傳入數據的一部分,需要潛在地爲多個前端和翻譯服務,並且您希望能夠輕鬆地在SQL中進行排序,因此我會預先計算一個查找表羅馬數字及其整數等於一些相當大的頁碼(32,767,也許,雖然你知道你的數據)。

只是重申,我假設有上頁碼一些合理的上限,你就不會被轉換什麼,你將需要數以百萬計值的查找表。這足以說服我在表示層中使用代碼。

有看似已經any number of functions out there,這樣你就不必另起爐竈創建該表。

即使你移動到未來的不同的方案,以羅馬數字輸入數據的想法意味着你可能總是需要這種類型的表,以便能夠導入圖書/章節。