假设我有下表:
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 ...
)
请注意,起始页和结束页字段是varchars。这样我就可以在前言中包含通常用罗马数字编号的页码。
我的问题是:修改此表和编写应用程序的有效方法是:
请记住以下条件/事实:
我最终可能会在不同的平台上以几种不同的语言实现它,因此首选代码无关的伪代码。
因为我正在处理成千上万的记录,所以我不能以编程方式遍历所有记录来执行排序等操作。因此,一些工作需要在数据库端进行。
使用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_label
和page_end_label
的值从罗马变为阿拉伯语。两个额外的整数加上该位意味着每个记录略多于8个字节的额外存储空间,大多数记录留下page_start_label
和page_end_label
空白我可能实际上保存< / em>空间!
这听起来像是一个合理的解决方案吗?或者我错过了潜在的陷阱/缺点?
答案 0 :(得分:1)
虽然我通常会将演示文稿详细信息留给表示层,但在这种情况下我同意@njk。
由于您将罗马数字作为传入数据的一部分,需要潜在地提供多个前端和翻译,并且您希望能够轻松地在SQL中排序,我会预先计算罗马的查找表数字和它们的整数等价物,直到某个相当大的页码(或许是32,767,尽管你知道你的数据)。
重申一下,我假设页码有一些合理的上限,你不会转换任何你需要数百万个值的查找表的东西。这足以说服我在表示层中使用代码。
似乎已经any number of functions out there,所以你不必重新发明轮子来创建这个表。
即使您将来转向其他方案,使用罗马数字传入数据的想法意味着您可能始终需要此类表格才能导入书籍/部分。