【问题标题】:Selective PostgreSQL database querying选择性 PostgreSQL 数据库查询
【发布时间】:2011-02-12 06:23:12
【问题描述】:

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

基本上,我有一个表格,其中每行包含一个由两到五个字符组成的序列 (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

它在概念上比最初看起来更简单,尤其是当您将其视为坐标系时。

【问题讨论】:

  • 您能发布 DDL 和一些示例数据吗?我很确定这是可以做到的,但不是你看到的那样。
  • 最好将示例数据发布为 INSERT 语句。控制台输出不能轻易用于快速设置测试环境
  • 我已经更新了 Gist,所以它应该包含正确的语句,但我没有测试它们,所以我不确定。
  • @Catcall 我再次更新了 Gist,因此它具有表定义和用于插入示例数据的 SQL 语句;不过,插入根字符数组的语法可能是错误的。
  • 我会小心使用数组。不熟悉您的域,tbl_root.root 的长度总是 3 吗?如果它可以改变长度或者你需要搜索它可能会成为一个非常头疼的问题。当您可以索引它们并知道这意味着什么时,数组就可以了,例如帐户周期的 Quarter[1] 独立存在。如果不是,你基本上有一个隐藏的嵌套表,不会是关系声音。

标签: database postgresql select


【解决方案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');

我很确定这样的结构会更容易查询,但你比我更了解你的领域。 (另一方面,数据库设计是我的专业……)


扩展我之前的答案和我们的 cmets,看看这个查询。 (测试表甚至不在 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

我们是否朝着正确的方向前进?

【讨论】:

  • 对此我不确定。它会使表格的结构不太清楚,因为数据应该在由“坐标”(根、表单、模式)访问的“三维空间”中表示。正如您所做的那样,展平模式表将导致某种辅助键来访问数据。是否有可能创建一个可以将表格重新排列为基于坐标的系统的视图?
  • 可能。 (另一种选择是使用电子表格查询数据库,以行、列和工作表的形式显示数据。)通常,如果您将表标准化为 5NF,那么您如何呈现数据几乎与它在数据库中的存储方式无关。数据库。换句话说,5NF 为您带来了很大的演示灵活性。我认为尝试对一小部分数据进行此操作以确保它适用于您的目的是有意义的。我不介意帮助你。
  • @Catcall 归一化为 5NF 是什么意思?
  • @zpqaeski:5NF 是“第五范式”的简写,一种用于提高数据完整性的数据库设计原则。它的一个副作用是使数据库更加灵活。见bkent.net/Doc/simple5.htm
  • 你有“所以,“女孩”这个词是由 id=2 的根给出的……根 = {s,ş,m}”。那应该是“id = 4的root”吗?
【解决方案2】:

嗯,这当然是一组奇怪的要求!这是我最好的猜测,但显然我还没有尝试过。我用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_idroot_lengthroot_formpattern 的字段。然后,您只需从单词表通过模式表连接到匹配所有正确条件的模式详细信息。

当然,也许我完全误解了您要查找的内容。如果是这样,如果您发布一些示例数据和示例结果会更清楚。

【讨论】:

  • 我正在考虑为每个长度创建一个单独的视图,然后在视图上使用 UNION。不过,我还没有查看示例数据和 DDL。
  • 我只是查找了视图的语法并为每个根长度创建了一个。我会暂时保留root_length 列,在确定不需要时将其删除。
猜你喜欢
  • 2018-01-03
  • 2023-02-10
  • 1970-01-01
  • 1970-01-01
  • 2012-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多