选择性PostgreSQL数据库查询

时间:2011-02-12 06:23:12

标签: database postgresql select

是否可以在PostgreSQL中根据已选择的行的值选择不同的表/列来进行选择性查询?

基本上,我有一个表,其中每行包含一个2到5个字符(tbl_roots)的序列,可选地带有一个长度字段,用于指定序列应包含的字符数(一旦我找到更好的方法,即通过计算序列的长度,它就意味着变得多余了。

有四个表包含模式(tbl_patterns_biliteraltbl_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_idroot_idpattern_idroot_formword)。每个单词被定义为特定长度和形式的根,拼接成特定模式。拼接相对简单:translate(pattern, '12345', array_to_string(root, '')) as word_combined完成工作。

现在,我想要做的是根据tbl_roots中序列的长度选择合适的模式表,并根据root_form的值选择模式表中的相应列。

怎么可以这样做?可以将它组合成一个简单的查询,还是需要进行多次传递?一旦我构建了这个查询,我就可以将它编码成一个可以搜索我的数据库的PHP脚本。

修改

这里有一些示例数据(它实际上是我目前正在使用的数据)以及有关系统如何运作的更多解释:https://gist.github.com/823609

它在概念上比最初看起来更简单,特别是如果你把它想象成一个坐标系。

2 个答案:

答案 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_detailspattern_idroot_lengthroot_form的字段列出pattern。然后,您只需从单词表通过模式表加入到符合所有正确标准的模式细节。

当然,也许我完全误解了你在寻找什么。如果是这样,如果您发布了一些示例数据和示例结果,那就更清楚了。