Выборочное обращение к базе данных PostgreSQL

Возможно ли иметь выборочные запросы в PostgreSQL, которые выбирают разные таблицы/столбцы на основе значений уже выбранных строк?

В принципе, у меня есть таблица, в которой каждая строка содержит последовательность из двух-пяти символов (tbl_roots), необязательно с полем длины, которое определяет, сколько символов должна содержать последовательность (она должна быть сделанный избыточным, когда я выясню лучший способ, т.е. подсчитав длину последовательностей).

Существует четыре таблицы, содержащие шаблоны (tbl_patterns_biliteral, tbl_patterns_triliteral,... и т.д.), каждая из которых соответствует root_length и пятой таблице (tbl_patterns), которая используется для синхронизации шаблона таблицы путем предоставления идентификатора для каждой строки, поэтому строка # 2 в tbl_patterns_biliteral соответствует той же строке в 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 script, который может выполнять поиск в моей базе данных.

ИЗМЕНИТЬ

Вот некоторые примеры данных (это фактически данные, которые я использую в данный момент) и еще несколько объяснений относительно того, как работает система: https://gist.github.com/823609

Это концептуально проще, чем кажется на первый взгляд, особенно если вы думаете об этом как о системе координат.

Ответ 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.

Мы движемся в правильном направлении?

Ответ 2

Ну, это, безусловно, странный набор требований! Здесь мое лучшее предположение, но, очевидно, я этого не пробовал. Я использовал UNION ALL для объединения шаблонов разных размеров, а затем отфильтровал их по длине. Возможно, вам придется переместить условие длины внутри каждого из подзапросов по причинам скорости, я не знаю. Затем я выбрал столбец, используя выражение CASE.

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. Затем вы просто присоединяетесь из таблицы слов через таблицу шаблонов к деталям шаблона, который соответствует всем правильным критериям.

Конечно, возможно, я совершенно неправильно понял, что вы ищете. Если это так, было бы яснее, если бы вы разместили некоторые данные примера и результат примера.