Выборочные запросы к базе данных PostgreSQL - PullRequest
0 голосов
/ 12 февраля 2011

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

EDIT

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

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

Ответы [ 2 ]

1 голос
/ 16 февраля 2011

Я думаю, вам придется изменить структуру ваших таблиц, чтобы иметь какую-то надежду.Вот первый черновик, о котором вы должны подумать.Я не уверен, каково значение «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 голосов
/ 12 февраля 2011

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

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

...