Выбор отдельных строк на основе значений из левой таблицы - PullRequest
1 голос
/ 09 марта 2011

Использование Postgres.Вот мой сценарий:

У меня есть три разные таблицы.Одним из них является титульный стол.Второе - это жанровая таблица.Третья таблица используется для соединения двух.Когда я проектировал базу данных, я ожидал, что у каждого заголовка будет один жанр высшего уровня.Заполнив его данными, я обнаружил, что были заголовки, которые имели два, иногда три жанра высшего уровня.

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

Я понимаю, что мне, вероятно, придется написать какую-то пользовательскую функцию, которая будет обрабатывать это для меня, но я подумал, что могу спросить, возможно ли сделать это без этого, просто чтобы убедиться,Я ничего не пропускаю.

Можно ли написать запрос, который позволит мне выбрать все отдельные названия независимо от количества жанров, которые у него есть, но также включить жанр?Или, что еще лучше, запрос, который даст мне строку жанров, разделенных запятыми, когда есть кратные числа?

Заранее спасибо!

Ответы [ 2 ]

4 голосов
/ 09 марта 2011

Звучит как работа для array_agg для меня. С такими таблицами:

create table t  (id int not null, title varchar not null);
create table g  (id int not null, name varchar not null);
create table tg (t int not null, g int not null);

Вы могли бы сделать что-то вроде этого:

SELECT t.title, array_agg(g.name)
FROM t, tg, g
WHERE t.id = tg.t
  AND tg.g = g.id
GROUP BY t.title, t.id

чтобы получить:

 title |       array_agg       
-------+-----------------------
 one   | {g-one,g-two,g-three}
 three | {g-three}
 two   | {g-two}

Тогда просто распакуйте массивы по мере необходимости. Если по какой-то причине вы действительно хотите использовать строку с разделителями-запятыми вместо массива, то string_agg ваш друг:

SELECT t.title, string_agg(g.name, ',')
FROM t, tg, g
WHERE t.id = tg.t
  AND tg.g = g.id
GROUP BY t.title, t.id

и вы получите что-то вроде этого:

 title |     string_agg      
-------+---------------------
 one   | g-one,g-two,g-three
 three | g-three
 two   | g-two

Я бы пошел с использованием массива, чтобы вам не пришлось беспокоиться о том, чтобы зарезервировать символ для разделителя или экранировать (а затем удалить) разделитель при агрегировании.

0 голосов
/ 09 марта 2011

Посмотрите на эту ветку , которая может ответить на ваш вопрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...