存储和查询每行不同的定价结构?
Storing and querying pricing structures which differ for each row?
我一直在努力想出一种存储这些数据的好方法...
每一行都是医生的做法。每种做法的价格因年龄段而异。例如,一种做法可能具有这种定价结构,其中左边是年龄,右边是价格:
0: 0
13: 20
21: 35
35: 35
60: 20
但是结构因实践而异。所以另一种做法可能是这样的:
0: 5
25: 50
40: 35
60: 20
我需要能够获取任何给定年龄的价格。
目前我将所有价格存储在每行的 JSONB 列中。我在 nodeJS 中获取 JSON 对象和 运行 一种算法来获取某个年龄段的价格。这当然不理想,但我想不出任何方法来在 postgres 中存储和查询它。
到目前为止,我考虑过另外 table 的费用,并像这样存储每个 age/price 对:
name | age | price
但这似乎有点笨拙并且会创建数千行。我的另一个想法是在练习行中为每个可能的年龄设置成本列,如下所示:
name | 0 | 5 | 6 | 13 | 16 | 18 | 21 | 25 | 40 | 60
但这也显得非常笨拙和笨拙。
有什么想法吗?或者,也许我最好将其保留在 JSON?
中
如果我没有理解错的话,价格取决于练习和年龄的结合。制作一个包含 3 列的 table 怎么样:
Practice_ID | Age | Price
其中 Practice_ID 和 Age 是主键。这样你就可以查询到价格和年龄。
我会将价格存储在单独的 table 中,该 table 定义价格有效的 "interval":
create table practice
(
id integer not null primary key,
name text
);
create table prices
(
practice_id integer not null references practice,
from_age integer not null,
to_age integer,
price integer not null,
constraint valid_interval check (from_age < to_age)
);
您还可以添加排除约束以防止间隔重叠:
CONSTRAINT no_overlap
EXCLUDE USING gist (practice_id WITH =, int4range(from_age, to_age) WITH &&)
当然,除了使用 from_age
和 to_age
两列之外,您还可以将其放入单个 int4range
列中,这具有可索引的优点。由于您通常会根据只留下极少数行的做法进行查询,因此范围列上的索引不是必需的(或无济于事)
查询价格,您只需:
select price
from prices
where practice_id = 42
and 25 between from_age and to_age
由于条件 practice_id = 42
已经将其缩小到仅 5 或 6 行,因此速度非常快。纵有千行。
我一直在努力想出一种存储这些数据的好方法...
每一行都是医生的做法。每种做法的价格因年龄段而异。例如,一种做法可能具有这种定价结构,其中左边是年龄,右边是价格:
0: 0
13: 20
21: 35
35: 35
60: 20
但是结构因实践而异。所以另一种做法可能是这样的:
0: 5
25: 50
40: 35
60: 20
我需要能够获取任何给定年龄的价格。
目前我将所有价格存储在每行的 JSONB 列中。我在 nodeJS 中获取 JSON 对象和 运行 一种算法来获取某个年龄段的价格。这当然不理想,但我想不出任何方法来在 postgres 中存储和查询它。
到目前为止,我考虑过另外 table 的费用,并像这样存储每个 age/price 对:
name | age | price
但这似乎有点笨拙并且会创建数千行。我的另一个想法是在练习行中为每个可能的年龄设置成本列,如下所示:
name | 0 | 5 | 6 | 13 | 16 | 18 | 21 | 25 | 40 | 60
但这也显得非常笨拙和笨拙。
有什么想法吗?或者,也许我最好将其保留在 JSON?
中如果我没有理解错的话,价格取决于练习和年龄的结合。制作一个包含 3 列的 table 怎么样:
Practice_ID | Age | Price
其中 Practice_ID 和 Age 是主键。这样你就可以查询到价格和年龄。
我会将价格存储在单独的 table 中,该 table 定义价格有效的 "interval":
create table practice
(
id integer not null primary key,
name text
);
create table prices
(
practice_id integer not null references practice,
from_age integer not null,
to_age integer,
price integer not null,
constraint valid_interval check (from_age < to_age)
);
您还可以添加排除约束以防止间隔重叠:
CONSTRAINT no_overlap
EXCLUDE USING gist (practice_id WITH =, int4range(from_age, to_age) WITH &&)
当然,除了使用 from_age
和 to_age
两列之外,您还可以将其放入单个 int4range
列中,这具有可索引的优点。由于您通常会根据只留下极少数行的做法进行查询,因此范围列上的索引不是必需的(或无济于事)
查询价格,您只需:
select price
from prices
where practice_id = 42
and 25 between from_age and to_age
由于条件 practice_id = 42
已经将其缩小到仅 5 或 6 行,因此速度非常快。纵有千行。