Получить переменное количество подмножеств с различными условиями - PullRequest
0 голосов
/ 27 декабря 2018

У меня есть следующая база данных:

CREATE TABLE IF NOT EXISTS city (
    id  serial primary key,
    name    character varying UNIQUE NOT NULL
);

CREATE TABLE IF NOT EXISTS inhabitants (
    id  serial primary key,
    fullname    character varying UNIQUE NOT NULL,
    home    integer REFERENCES city
);

INSERT INTO city (name) VALUES
('michigan'),
('washington'),
('new york'),
('london'),
('los angeles')
ON CONFLICT DO NOTHING;

INSERT INTO inhabitants (fullname, home) VALUES
('flannigan, amy', 1),
('hannigan, leon', 1),
('shennanigan, frank', 1),
('catcher, floyd', 2),
('rice, amy', 2),
('black, joe', 2),
('higgins, simon', 3),
('stewart, rick', 3),
('white, frank', 3),
('henson, ben', 5),
('hedge, tim', 5),
('wilson, bill', 5),
('moriarty, doc', 4),
('fletcher, dolores', 4),
('fletcher, hank', 4),
('williamson, ann', 1),
('stewart, mary', 3)
ON CONFLICT DO NOTHING;

Я хочу извлечь различное количество подмножеств с различным количеством жителей для каждого подмножества.В настоящее время я использую запрос для каждого подмножества, например, если мне нужно два подмножества, я могу использовать эти два запроса:

select fullname, home from inhabitants i
where home = (SELECT id FROM city WHERE name = 'michigan')
ORDER BY random() LIMIT 2;

и

select fullname, home from inhabitants i
where home = (SELECT id FROM city WHERE name = 'london')
ORDER BY random() LIMIT 1;

Результаты могут выглядеть следующим образом:

    fullname     | home 
-----------------+------
 hannigan, leon  |    1
 williamson, ann |    1
(2 rows)

и

     fullname      | home 
-------------------+------
 fletcher, dolores |    4
(1 row)

Я присоединяю эти два результата в Bash, чтобы они выглядели так, как я хочу:

    fullname       | home 
-------------------+------
 hannigan, leon    |    1
 williamson, ann   |    1
 fletcher, dolores |    4
(3 rows)

Я хотел бы свести к минимумуколичество вызовов базы данных.

Есть ли способ сделать это с помощью одного запроса (или функции) или, по крайней мере, лучше, чем то, что я делаю в настоящее время?

1 Ответ

0 голосов
/ 27 декабря 2018

Использовать оконные функции:

select fullname, home 
from (select i.*, 
             row_number() over (partition by home order by random()) as seqnum
      from inhabitants i
     ) i join
     city c
     on c.id = i.home
where (name = 'michigan' and seqnum <= 2) or
      (name = 'london' and seqnum <= 1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...