powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Запрос с join и pagination
20 сообщений из 20, страница 1 из 1
Запрос с join и pagination
    #39006413
bemtaill
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброго времени суток!

Положим есть 2 таблицы:
City
Код: plaintext
1.
2.
3.
4.
| Id | Name    |
| 1  | Moscow  |
| 2  | London  |
| 3  | Paris   |

Person
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
| Id | CityId   | LastName |
| 1  | 1        | Vasya    | 
| 2  | 1        | Petya    |
| 3  | 1        | Olga     |
| 4  | 2        | Greg     |
| 5  | 2        | Andy     |
| 6  | 3        | Francos  |
те 1:N. Мне необходимо написать запрос который бы возвращал, скажем, два города ( второй и третий ) вместе с всеми людьми которые в них проживают. Получается нужно что-то вроде:
Код: plsql
1.
SELECT * FROM City c JOIN Person p ON (c.id=p.CityId) ORDER BY c.Id OFFSET ??? LIMIT ???


Вот что прописать в OFFSET и LIMIT не понятно. Есть идеи как все это замутить с использованием вложенного SELECT, но коряво это. Наверняка есть более элегантное решение?

Спасибо!
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39006418
p2.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bemtaillВот что прописать в OFFSET и LIMIT не понятно.тут должен быть вопрос не что прописать, а куда...
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39006429
bemtaill
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ок, куда? )
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39006447
p2.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bemtaillок, куда? )в тот самый "вложенный SELECT".
Код: sql
1.
2.
3.
4.
select *
from (table city order by id offset 1 limit 2) c
join person p  on c.id=p.cityid
order by c.id, p.id
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39006556
bemtaill
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
p2.,

Спасибо, это работает, но я изначально слишком сократил постановку задачи для простоты. На самом деле:
Мне необходимо написать запрос который бы возвращал, скажем, два города с людьми в них проживающих имена которых содержат букву "a" .

Т.е. если в городе Х нет людей с буквой "a", то возвращать город не надо. Поверх этого, как я ранее говорил, нужно пагинация.
Как-то так.
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39006651
Фотография Щукина Анна
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bemtaillp2.,

Спасибо, это работает, но я изначально слишком сократил постановку задачи для простоты. На самом деле:
Мне необходимо написать запрос который бы возвращал, скажем, два города с людьми в них проживающих имена которых содержат букву "a" .

Т.е. если в городе Х нет людей с буквой "a", то возвращать город не надо. Поверх этого, как я ранее говорил, нужно пагинация.
Как-то так.Добавьте это условие в ON-секцию вашего джойна. Джойн же "внутренний" - если людей на букву "А" в городе нет, город и не вернется в результат запроса...
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39006749
p2.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Щукина АннаДобавьте это условие в ON-секцию вашего джойна. тогда может вернуться меньше двух city, несмотря на наличие городов с жителями 'а'.
вместо limit тогда использовать подзапрос с dense_rank. И, в зависимости от того, нужны ли все жители или только 'а', - first_value, max или прочую аналитику для размножения результатов критерия на все строки города. Впрочем по производительности это может оказаться дороже второго обращения к person.
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39006817
bemtaill
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
p2.,

Спасибо, надо будет въехать в window functions сначала. Посмотрю сегодня.
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39015212
bemtaill
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
p2.,

Почитал, но так и не смог прикрутить dense_rank. Кроме того, постгрес ругается на max(dense_rank...):
aggregate function calls cannot contain window function calls.


Не могли бы вы немного более развернуто описать как можно решить проблему с использованием dense_rank?
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39015755
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bemtaill,

а что вам мешает проверять наличие -- exists -ом, а вывод осуществлять как и раньше. с большой вер-ю exists будет дешёвым.

правда от пагинации оффсетом я бы уходил [нужен индекс по (cityid,lastname,id[уникализирующее]) ]. если вы берете клиентом следующую страничку -- листать первую страницу от достигнутого.
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39017442
bemtaill
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwq,

Если я вас правильно понял, то в этом случае будет что-то вроде:

SELECT * FROM City c JOIN Person p ON (c.id=p.CityId) WHERE exists (SELECT * FROM Person p WHERE p.name LIKE '%a%') OFFSET ??? LIMIT ???


хотя я наверное вас не правильно понял, тк этот подход не решает проблему (
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39017491
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bemtaill,

торопицца ненада, да
по полочкам:
сначала возьмите 2 и только 2 сити (по p2), в которых EXISTS()
потом возьмите джойн на персоны, с лимитом и оффсетами.

так понятно ? или мало разжевать -- ещё и побуквенно записать модификацию вот этого вот 17888271 требуется ?
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39017705
bemtaill
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwq,

Не понятно, разжуете?
Когда сделаю джойн "проверенных esists-ом" записей с Person, количество записей в результате этого джойна неизвестно (тк city <-> person 1:N). Что вы напишете в LIMIT/OFFSET?
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39017892
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bemtaillqwwq,

Не понятно, разжуете?
Когда сделаю джойн "проверенных esists-ом" записей с Person, количество записей в результате этого джойна неизвестно (тк city <-> person 1:N). Что вы напишете в LIMIT/OFFSET?

Совершенно очевидно помоему.
1)сначала выбираем нужные нам города
Код: plsql
1.
SELECT DISTINCT p1.CityId FROM Person p1 WHERE p1.name LIKE '%a%' ORDER BY p1.CityId OFFSET 1 LIMIT 2



2)потом по этим городам выбираем всех персон
Код: plsql
1.
SELECT * FROM City c JOIN Person p ON (c.id=p.CityId) WHERE c.id IN (SELECT DISTINCT p1.CityId FROM Person p1 WHERE p1.name LIKE '%a%' ORDER BY  p1.CityId OFFSET 1 LIMIT 2) AND p.name LIKE '%a%' 



Собственно все.


--
Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39017971
bemtaill
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,

Согласен с вами, и это единственное решение которое я смог найти на данный момент:
bemtaill...
Есть идеи как все это замутить с использованием вложенного SELECT, но коряво это. Наверняка есть более элегантное решение?
...

Проблема в том что эти SQL запросы генерятся автоматически Java приложением на основе некого domain-specific language и в реальности и без вложенного селекта выглядят пугающе. Проблема с этим вложенным селектом в том что придется дублировать "WHERE p1.name LIKE '%a%'" (в реальном кэйсе это может быть WHERE с 10-30 термами). Все это продублированное в перемешку с джойнами, сортировками и тд делает такие запросы не сложными для понимания и дебага в случае проблем. Вот тут была идея с подзапросом с dense_rank, но в силу своего слабоумия я так и не понял как ее прикрутить.
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39017972
bemtaill
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bemtaill,

* сложными
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39017995
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bemtaillMaxim Boguk,

Согласен с вами, и это единственное решение которое я смог найти на данный момент:
bemtaill...
Есть идеи как все это замутить с использованием вложенного SELECT, но коряво это. Наверняка есть более элегантное решение?
...

Проблема в том что эти SQL запросы генерятся автоматически Java приложением на основе некого domain-specific language и в реальности и без вложенного селекта выглядят пугающе. Проблема с этим вложенным селектом в том что придется дублировать "WHERE p1.name LIKE '%a%'" (в реальном кэйсе это может быть WHERE с 10-30 термами). Все это продублированное в перемешку с джойнами, сортировками и тд делает такие запросы не сложными для понимания и дебага в случае проблем. Вот тут была идея с подзапросом с dense_rank, но в силу своего слабоумия я так и не понял как ее прикрутить.

чтобы не дублировать условия можно через WITH сделать (и скорее всего это будет быстрее в итоге)
Код: plsql
1.
2.
WITH all_res AS (SELECT * FROM City c JOIN Person p ON (c.id=p.CityId) WHERE p.name LIKE '%a%' )
SELECT * FROM all_res WHERE CityId IN (SELECT DISTINCT CityId FROM all_res ORDER BY CityId OFFSET 1 LIMIT 2)



при этом вторая часть вообще на зависит от начальных условий.

--
Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39018009
bemtaill
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,

Выглядит секси:) Спасибо!
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39018192
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bemtaillMaxim Boguk,

Выглядит секси:) Спасибо!

Надо понимать что в общем случае на большой базе такая постановка задачи вообще не имеет хорошего решения от слова совсем.
Так что если там у вас десятки миллионов Person и популярный фильтр (под который много людей попадает)
- все будет очень медленно.
Впрочем постановка " вместе с всеми людьми которые в них проживают" - она гарантированно будет давать медленный ответ на больших городах.

--
Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
Запрос с join и pagination
    #39018240
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,

если вы стали модератором -- это не значит, что вы в состоянии оценить , что технически важно, а что -нет.

более того , мы уже выяснили в одной из задач [про txid и mod 32], что я болван, а вы с мишей -- так вообще образцовые дятлы.
это печально. но факт.

т.ч. потрудитесь в следующий раз оставить автограф о своей проф-непригодности как модератора. чтобы я вас с кем-то не путал.
заранее спасибо.


PS единственное, что я пытался донести до ТС -- что он решает не ту задачу и не в той постановке.

К удалённой профнепригодным модером модели (если кто-то потрудится её восстановить -- будет замечательно):

допустим у нас имеется исчерпывающий справочник имён. И индекс по Сити-персонам. Тогда сразу появляется возможность взять выборку содержащих "буковку" имен от справочника (он уже "дистинкнутый"), далее взять те сити, где EXISTS(имена из фильтрованного списка) [ -- вдоль упомянутого индекса, если кто не заметил], и далее взять простую выборку с LIMIT вдоль того же индекса.

Или если мы , помня , что имена небольшие, построим gist/gin индекс по массивам их буковок (что затратно, конечно) -- мы сразу получаем возможность брать быстрый exists, но страничку придется строить с блекд фильтрами и сортировкой (если нет того самого индекса по (city,person)) до того как взять оффсеты и лимит

ну и т.п.
т.е. в большинстве случаев, когда мы позаботились о внятной организации хранения, задачу фильтрации "городов" можно решить запросом на сущ-е [как правило -- однократным index seek] с использованием того или иного индекса.
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Запрос с join и pagination
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]