PostgreSQL 9.2 的一項(xiàng)新特性就是范圍類(lèi)型 range types,通過(guò)這個(gè)名字你可以輕松猜出該類(lèi)型的用途,它可讓你為某列數(shù)據(jù)定義數(shù)值范圍。
這個(gè)簡(jiǎn)單的特性可以讓我們不需要定義兩個(gè)字段來(lái)描述數(shù)值的開(kāi)始值和結(jié)束值,一個(gè)最直觀的例子就是:
postgres# CREATE TABLE salary_grid (id int, position_name text, start_salary int, end_salary int);
CREATE TABLE
postgres# INSERT INTO salary_grid VALUES (1, 'junior developper', 20000, 30000);
INSERT 0 1
postgres# INSERT INTO salary_grid VALUES (2, 'senior developper', 28000, 35000);
INSERT 0 1
postgres# INSERT INTO salary_grid VALUES (3, 'postgres developper', 50000, 70000);
INSERT 0 1
這個(gè)簡(jiǎn)單的關(guān)系用于存儲(chǔ)一個(gè)給定的職位和待遇的范圍(你還需要確定工資的貨幣單位),重要的是你必須實(shí)現(xiàn)一些系統(tǒng)函數(shù)或者外部程序 API 來(lái)執(zhí)行例如范圍的交叉或者聯(lián)合。
Postgres 9.2 允許你的應(yīng)用直接在數(shù)據(jù)庫(kù)端實(shí)現(xiàn)范圍值,范圍類(lèi)型包括:
- 4 位整數(shù)范圍, int4range
- 8 位整數(shù)范圍, int8range
- 數(shù)值范圍, numrange
- 無(wú)時(shí)區(qū)的時(shí)間戳范圍, tsrange
- 帶時(shí)間戳的時(shí)間范圍, tstzrange
- 日期范圍, daterange
你也可以定義自己的范圍類(lèi)型,Postgre 官網(wǎng)文檔給出了 float 的示例:
postgres# CREATE TYPE floatrange AS RANGE (
postgres# subtype = float8,
postgres# subtype_diff = float8mi);
有了這樣一個(gè)功能,我們前面提到的工資表格例子就可以改為:
postgres=# create table salary_grid (id int, position_name text, salary_range int4range);
CREATE TABLE
postgres=# INSERT INTO salary_grid VALUES (1, 'junior developper', '[20000, 30000]');
INSERT 0 1
postgres=# INSERT INTO salary_grid VALUES (2, 'senior developper', '[28000, 35000]');
INSERT 0 1
postgres=# INSERT INTO salary_grid VALUES (3, 'postgres developper', '[50000, 70000]');
INSERT 0 1
postgres=# select * from salary_grid;
id | position_name | salary_range
----+---------------------+---------------
1 | junior developper | [20000,30001)
2 | senior developper | [28000,35001)
3 | postgres developper | [50000,70001)
(3 rows)
很重要的一點(diǎn)是,如果使用的是括號(hào)(),元組數(shù)據(jù)的上界是排除在外的,而中括號(hào)[]則上界包含其中。
數(shù)據(jù)庫(kù)本身也包含不同的用于處理范圍類(lèi)型的函數(shù)。
你可直接獲取一個(gè)給定范圍的最低和最高值:
postgres=# SELECT upper(salary_range), lower(salary_range) FROM salary_grid;
upper | lower
-------+-------
30001 | 20000
35001 | 28000
70001 | 50000
(3 rows)
你可以檢查某個(gè)值是否包含在給定范圍內(nèi):
postgres=# SELECT salary_range @> 4000 as check
postgres=# FROM salary_grid
postgres=# WHERE position_name = 'junior developper';
check
-------
f
(1 row)
這里顯示 4000 并不包含在初級(jí)職位的待遇里 [20000,30000].
這里稍微復(fù)雜了一些,你還可以檢查兩個(gè)范圍之間的重疊的部分,這里的 salary_range 使用的是 int4,因此 int4range 函數(shù)可用于此操作:
postgres=# WITH junior_salary AS (
SELECT salary_range as junior
FROM salary_grid
WHERE position_name = 'junior developper'),
senior_salary AS (
SELECT salary_range as senior
FROM salary_grid
WHERE position_name = 'senior developper')
SELECT int4range(junior) int4range(senior) as check
FROM junior_salary, senior_salary;
check
-------
t
(1 row)
這里顯示的是初級(jí)和高級(jí)職位之間的工資重疊部分。
你還可以設(shè)定無(wú)上下限的范圍類(lèi)型,或者是只有上限或者下限的范圍類(lèi)型,讓我們來(lái)看一個(gè)非?,F(xiàn)實(shí)的例子:
postgres# UPDATE salary_grid SET salary_range = '[50000,)' WHERE position_name = 'postgres developper';
UPDATE 0 1
postgres=# SELECT salary_range @> 60000000 as check
postgres-# FROM salary_grid WHERE position_name = 'postgres developper';
check
-------
t
(1 row)
你可以使用 lower_inf 或者 upper_inf 來(lái)檢查范圍的無(wú)限值。
Postgres 還有其他一些內(nèi)嵌的函數(shù)(如 isempty),這個(gè)可以直接從官方文檔中獲取詳細(xì)信息。
你還可以閱讀《PostgreSQL 的數(shù)組》
您可能感興趣的文章:- 詳細(xì)講解PostgreSQL中的全文搜索的用法
- 使用Bucardo5實(shí)現(xiàn)PostgreSQL的主數(shù)據(jù)庫(kù)復(fù)制
- 在PostgreSQL的基礎(chǔ)上創(chuàng)建一個(gè)MongoDB的副本的教程
- 在PostgreSQL中使用數(shù)組時(shí)值得注意的一些地方
- 使用Ruby on Rails和PostgreSQL自動(dòng)生成UUID的教程
- 在PostgreSQL中使用日期類(lèi)型時(shí)一些需要注意的地方
- 一個(gè)提升PostgreSQL性能的小技巧
- 在PostgreSQL中實(shí)現(xiàn)遞歸查詢(xún)的教程
- 在PostgreSQL上安裝并使用擴(kuò)展模塊的教程
- 深入解讀PostgreSQL中的序列及其相關(guān)函數(shù)的用法