2011-02-12 46 views
0

是否可以在PostgreSQL中進行選擇性查詢,根據已選擇的行的值選擇不同的表/列?Selective PostgreSQL數據庫查詢

基本上,我有一個表格,其中每行包含一個由兩到五個字符組成的序列(tbl_roots),可選地帶有一個長度字段,該長度字段指定該序列應該包含多少個字符(它的意思是一旦我找出更好的方法,即通過計算序列的長度)。

有含圖案(tbl_patterns_biliteraltbl_patterns_triliteral,...等)四個表,其中的每一個對應於一個root_length,並用於通過提供用於每個的標識符以同步模式表的第五表(tbl_patternstbl_patterns_biliteral中的行排列#2對應於tbl_patterns_triliteral中的同一行。這六個模式表受到限制,使得tbl_patterns_(bi|tri|quadri|quinqui)literal中的任何行都不會存在tbl_patterns中不存在的pattern_id

每個模式表有九個其他列對應於一個標識符(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

它比它出現在概念上更簡單首先,特別是如果你把它看作一個座標系。

+0

你可以發表DDL和一些樣本數據嗎?我非常確定這可以完成,但不像你看待它。 – 2011-02-12 07:18:17

+0

示例數據最好以INSERT語句發佈。控制檯輸出不能很容易地用於快速設置測試環境 – 2011-02-12 09:28:09

+0

我已經更新了Gist,因此它應該包含正確的語句,但我沒有測試它們,所以我不確定。 – Robbie 2011-02-12 10:55:37

回答

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

我們正朝着正確的方向前進嗎?

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_formpattern。然後,您只需通過模式表將單詞表連接到匹配所有正確條件的模式詳細信息。

當然,也許我完全誤解了你要找的東西。如果是這樣,如果您發佈了一些示例數據和示例結果,則會更清楚。