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

Столкнулся тут с проблемой сортировки,
Есть пользователи у каждого из которых есть имя и некий рейтинг:
Код: plsql
1.
2.
3.
4.
5.
6.
CREATE TABLE user (
    id BIGINT,
    name TEXT,
    rating REAL,
    sort INTEGER
);



собственно сейчас все делается на уровне приложения:
Код: javascript
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
// Получаем список пользователей из двух частей
var where = "/* тут выражение для фильтрации */";
var normal = SQL("SELECT * FROM user WHERE "+where+" AND rating >= 0 ORDER BY rating DESC");
var looser = SQL("SELECT * FROM user WHERE "+where+" AND rating < 0 ORDER BY sort");
// Ну а потом их выводим
for (i = 0; i < 3; i++) { // Чередуем пользователей из разных списков
  if (normal.length) output(normal.shift());
  if (looser.length) output(looser.shift());
}
// Выводим все что осталось
while (normal.length) output(normal.shift());
while (looser.length) output(looser.shift());



Очень хотелось-бы вывести все это с помощью одного SQL выражения типа:

Код: sql
1.
SELECT * FROM user WHERE id IN (sort_function("/* выражение для фильтрации */"))


или
Код: sql
1.
SELECT * FROM user WHERE /* выражение для фильтрации */ ORDER BY sort_function(...)



Все что приходит в голову это смотреть в сторону WITH RECURSIVE или WINDOW FUNCTION
...
Рейтинг: 0 / 0
Объединение двух запросов
    #38815483
Alexius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chernomyrdin,

window функции вполне подходят, можно как-то так попробовать:

Код: sql
1.
select rank() over(order by rating desc) + rank() over(order by (case when rating < 0 then sort end)), * from user where ... order by 1 desc
...
Рейтинг: 0 / 0
Объединение двух запросов
    #38815486
Alexius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexius,

order by 1 в конце без desc, конечно
...
Рейтинг: 0 / 0
Объединение двух запросов
    #38815527
Фотография chernomyrdin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
BEGIN; 
CREATE TEMP TABLE "user" (
    id BIGINT,
    name TEXT,
    rating REAL,
    sort INTEGER
);
INSERT INTO "user" VALUES
    (11,'user 1', 100,(10*random())::integer),
    (12,'user 2', 110,(10*random())::integer),
    (13,'user 3', 120,(10*random())::integer),
    (14,'user 4', 115,(10*random())::integer),
    (15,'user 5', 101,(10*random())::integer),

    (16,'looser 1', -2,(10*random())::integer),
    (17,'looser 2', -3,(10*random())::integer),
    (18,'looser 3', -1,(10*random())::integer),
    (19,'looser 4', -7,(10*random())::integer),
    (20,'looser 5', -2,(10*random())::integer),
    (21,'looser 6', -3,(10*random())::integer),
    (22,'looser 7', -5,(10*random())::integer),

    (23,'zero 1', 0,(10*random())::integer),
    (24,'zero 2', 0,(10*random())::integer),
    (25,'zero 3', 0,(10*random())::integer);

select rank() over(order by rating desc) + rank() over(order by (case when rating < 0 then sort end)), * from "user" where TRUE order by 1;



Получаем:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
 ?column? | id |   name   | rating | sort 
----------+----+----------+--------+------
        9 | 13 | user 3   |    120 |    3
       10 | 14 | user 4   |    115 |    2
       11 | 20 | looser 5 |     -2 |    1
       11 | 12 | user 2   |    110 |    4
       12 | 15 | user 5   |    101 |    5
       13 | 11 | user 1   |    100 |    3
       13 | 18 | looser 3 |     -1 |    8
       14 | 23 | zero 1   |      0 |    9
       14 | 25 | zero 3   |      0 |   10
       14 | 24 | zero 2   |      0 |    9
       15 | 21 | looser 6 |     -3 |    4
       16 | 17 | looser 2 |     -3 |    8
       16 | 22 | looser 7 |     -5 |    3
       17 | 16 | looser 1 |     -2 |    9
       19 | 19 | looser 4 |     -7 |    8
Оно как-бы получается интереснее, чем просто ORDER BY rating DESC, но не совсем то.
Пошел медитировать над rank(), и возможностью написать свою aggregate функцию что-бы результаты были как-бы более упорядоченными :-)
...
Рейтинг: 0 / 0
Объединение двух запросов
    #38815553
Alexius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chernomyrdin,

тогда вот так:
Код: sql
1.
select least(row_number() over(order by rating desc), row_number() over(order by (case when rating < 0 then sort end))), * from "user" where TRUE order by 1;
...
Рейтинг: 0 / 0
Объединение двух запросов
    #38816135
Фотография chernomyrdin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот что у меня получилось:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
WITH
    u AS (SELECT id,rating,sort FROM "user" WHERE TRUE),
    f AS (
        (SELECT row_number() OVER (ORDER BY rating DESC) as r, * FROM u WHERE rating > 0 ORDER BY 1 limit 5)
        UNION ALL
        (select row_number() over (ORDER BY sort)        as r, * FROM u WHERE rating < 0 ORDER BY 1 limit 5)
    )
SELECT s.* /* , o.name */
FROM (
    (SELECT id,rating,sort FROM f                  ORDER BY r,rating DESC)
    UNION ALL
    (SELECT id,rating,sort FROM u WHERE rating > 0 ORDER BY rating DESC OFFSET 5)
    UNION ALL
    (SELECT id,rating,sort FROM u WHERE rating < 0 ORDER BY sort OFFSET 5)
    UNION ALL
    (SELECT id,rating,sort FROM u WHERE rating = 0 ORDER BY sort)
) AS s /* LEFT JOIN "user" AS o ON (o.id = s.id) */;



Только почему-то в случае раскомментирования того что закомментировано вся сортировка слетает :-(
С реальными данными вроде как нормально, но тенденция по слету сортировки мне не нравится
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Объединение двух запросов
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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