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