是否可以在PostgreSQL中根据已选择的行的值选择不同的表/列来进行选择性查询?
基本上,我有一个表,其中每行包含一个2到5个字符(tbl_roots
)的序列,可选地带有一个长度字段,用于指定序列应包含的字符数(一旦我找到更好的方法,即通过计算序列的长度,它就意味着变得多余了。
有四个表包含模式(tbl_patterns_biliteral
,tbl_patterns_triliteral
,...等),每个表对应一个root_length
和第五个表(tbl_patterns
)用于通过为每行提供标识符来同步模式表 - 因此tbl_patterns_biliteral
中的行#2对应于tbl_patterns_triliteral
中的同一行。六个模式表受到限制,tbl_patterns_(bi|tri|quadri|quinqui)literal
中的任何行都不能pattern_id
中不存在tbl_patterns
。
每个模式表都有九个其他列,对应于标识符(root_form
)。
数据库中的最后一个表(tbl_words
)包含每个主要表格的列(word_id
,root_id
,pattern_id
,root_form
,word
)。每个单词被定义为特定长度和形式的根,拼接成特定模式。拼接相对简单:translate(pattern, '12345', array_to_string(root, '')) as word_combined
完成工作。
现在,我想要做的是根据tbl_roots
中序列的长度选择合适的模式表,并根据root_form
的值选择模式表中的相应列。
怎么可以这样做?可以将它组合成一个简单的查询,还是需要进行多次传递?一旦我构建了这个查询,我就可以将它编码成一个可以搜索我的数据库的PHP脚本。
修改
这里有一些示例数据(它实际上是我目前正在使用的数据)以及有关系统如何运作的更多解释:https://gist.github.com/823609
它在概念上比最初看起来更简单,特别是如果你把它想象成一个坐标系。
答案 0 :(得分:1)
我认为您将不得不改变表格的结构以获得任何希望。这是你想到的第一稿。我不确定“i”,“ii”和“iii”在列名中的含义是什么。在我的无知中,我假设它们对你有意义,所以我把它们保存在下表中。 (我将它们的信息保存为整数。如果重要的话,很容易将其改为小写罗马数字。)
create table patterns_bilateral (
pattern_id integer not null,
root_num integer not null,
pattern varchar(15) not null,
primary key (pattern_id, root_num)
);
insert into patterns_bilateral values
(1,1, 'ya1u2a'),
(1,2, 'ya1u22a'),
(1,3, 'ya12u2a'),
(1,4, 'me11u2a'),
(1,5, 'te1u22a'),
(1,6, 'ina12u2a'),
(1,7, 'i1u22a'),
(1,8, 'ya1u22a'),
(1,9, 'e1u2a');
我很确定像这样的结构会更容易查询,但你比我更了解你的领域。 (另一方面,数据库设计是我的领域......)
扩展我之前的回答和评论,看看这个查询。 (测试表甚至不在3NF,但现在表格并不重要。)
create table test (
root_id integer,
root_substitution varchar[],
length integer,
form integer,
pattern varchar(15),
primary key (root_id, length, form, pattern));
insert into test values
(4,'{s,ş,m}', 3, 1, '1o2i3');
这是重要的部分。
select root_id
, root_substitution
, length
, form
, pattern
, translate(pattern, '12345', array_to_string(root_substitution, ''))
from test;
该查询除其他外还返回翻译soşim
。
我们正朝着正确的方向前进吗?
答案 1 :(得分:0)
嗯,这肯定是一组奇怪的要求!这是我最好的猜测,但显然我没有尝试过。我使用UNION ALL
来组合不同大小的模式,然后根据长度过滤它们。出于速度原因,您可能需要在每个子查询中移动长度条件,我不知道。然后我使用CASE
expression选择了该列。
select word,
translate(
case root_form
when 1 then patinfo.pattern1
when 2 then patinfo.pattern2
... up to pattern9
end,
'12345',
array_to_string(root.root, '')) as word_combined
from tbl_words word
join tbl_root root
on word.root_id = root.root_id
join tbl_patterns pat
on word.pattern_id = pat.pattern_id
join (
select 2 as pattern_length, pattern_id, pattern1, ..., pattern9
from tbl_patterns_biliteral bi
union all
select 3, pattern_id, pattern1, pattern2, ..., pattern9
from tbl_patterns_biliteral tri
union all
...same for quad and quin...
) patinfo
on
patinfo.pattern_id = pat.pattern_id
and length(root.root) = patinfo.pattern_length
考虑将所有不同的模式合并到一个pattern_details
表中,并使用root_length
字段进行过滤。我认为这比将它们与UNION ALL
组合在一起更容易。如果pattern_details
表中有多行并基于root_form
进行过滤,则可能会更容易。最好的方法是使用pattern_details
,pattern_id
,root_length
和root_form
的字段列出pattern
。然后,您只需从单词表通过模式表加入到符合所有正确标准的模式细节。
当然,也许我完全误解了你在寻找什么。如果是这样,如果您发布了一些示例数据和示例结果,那就更清楚了。