我一直在努力解决这个问题,现在试图找出如何最有效地做到这一点。
问题如下。我在数据库中有针对特定年龄段销售的商品,例如ages 10 to 20
或ages 16+
,我需要能够进行查询,例如find item that is for 17 year old
这是我最好的两个想法(但我也不喜欢,因为我认为它们效率低下)。
拥有一个csv列,其值为10-20
和16+
,检索整个列表,并通过它进行解析(不好主意,我知道,虽然这里的想法很新鲜)
为csv列添加类似10,11,12,13...20
的值作为范围,因此我可以使用WHERE ages LIKE "%17%"
查找它,对于像16+
这样的情况,我必须检索这些使用类似WHERE ages LIKE "%+%"
之类的特殊情况并通过这些解析。
我当然倾向于第二种选择,但在最好的情况下,我正在运行两个查询,一个用于常规项目,另一个用于16+
有更好的方法吗?如果没有,你认为你可以让我的模型更高效吗?感谢。
答案 0 :(得分:3)
你可以这样做:
lower_age
和upper_age
列添加到表中,两个整数都允许NULL。lower_age
为NULL,则没有下限。upper_age
为NULL,则没有上限。澄清(4),你想说这样的话:
select *
from your_table
where $n between coalesce(lower_age, $n) and coalesce(upper_age, $n)
其中$n
是您正在寻找的年龄。 BETWEEN使用包含边界,因此coalesce(lower_age, $n)
如果$n
不为NULL则忽略lower_age
并且如果$n >= $n
为NULL,则为lower_age
(即该边界上的自动为真) ;同样适用于upper_age
。
如果某些内容仅适用于11岁的孩子,则[lower_age,upper_age]
关闭时间间隔为[11, 11]
,其中16岁为[16, NULL]
,6岁及以下为[NULL, 6]
,每个人都是[NULL, NULL]
,没有人会[23, 11]
或其他任何lower_age > upper_age
(或者更有可能的是,CHECK约束会使其无效的数据)。< / p>
答案 1 :(得分:1)
您可以通过多种方式实现这一目标。如果您在行中存储用户的年龄(无论如何)。然后您可以查询年龄并使用&gt; 16或者&lt; 30或10-20之间无论如何。另一种选择是将其存储为按位。有一个参考表并存储您的不同范围,如果它们可以有倍数,那么您只需将两个行值相加。
1 = 10
2 = 16+
4 = 10-20
8 = 20-30
16 = 20+
32 = 30+
.
.
.
.
然后在存储人员信息的表中,您可以将列设置为int或bigint,取您的偏好,然后对于他们所属的任何组,您可以通过数字来确定,例如:
Table of Users
ID Name BitWise
1 test 2
2 something 6 (2+4)
3 blah 24 (8+16)
然而,我认为这可能有点矫枉过正,你可能最好只将年龄存储为一个正在运行的查询。这很可能是效率最高的。
答案 2 :(得分:1)
你有一系列的选择(没有双关语意)。对于年龄建议,最简单的方法是存储min_age和max_age并进行如下查询:
select * from item where :age between min_age and max_age
您必须决定是否允许这些列的空值(然后您需要使用coalesce()或nvl()或数据库提供的用于处理与空值的比较的任何函数),或者为这些列设置边界值你可以肯定:年龄总会介于两者之间。
或者,您可以使用m:n表
create table item_ages (item_id int not null, age int not null, constraint item_ages_pk primary key (item_id, age)
并用显式值填充:
item_id | age
-------------
1 | 16
1 | 17
1 | 18
等等。这比使用范围更麻烦,但也更灵活,并且由于您的数据库可以索引表并可能将该索引存储在内存中,因此查询应该很快。输入新项目或特定项目的年龄范围发生变化时,您只需触摸此表格。
请注意,CBRRacer的答案具有类似的属性:两者都有一个想法,即您准备一个可以轻松编制索引的数据结构,并回答该索引中的过滤器问题。这是一种在电子商务应用程序中存储营销数据的流行方法。该范围的最终目的是使用专用包来存储用于该目的的反向索引。但是对于一个简单的年龄建议来说当然是矫枉过正的。
答案 3 :(得分:0)
这样的事情:
SELECT * FROM tablename WHERE 17 BETWEEN start_age AND end_age