Как быстро отсортировать по рассчитанным критериям в Postgres? - PullRequest
0 голосов
/ 19 сентября 2019

Мне нужно написать запрос сортировки записей по динамически рассчитанным критериям.В каждой ячейке имеется двумерный массив 12x12, в котором указано количество точек.Точки распределяются вдоль диагоналей (т.е. все элементы главной диагонали дают 6 баллов)

+----+---+---+---+---+---+---+---+---+---+----+----+----+
| №  | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
+----+---+---+---+---+---+---+---+---+---+----+----+----+
|  1 | 6 | 4 | 5 | 2 | 7 | 3 | 1 | 6 | 7 |  2 |  5 |  6 |
|  2 | 4 | 6 | 4 | 5 | 2 | 7 | 3 | 1 | 6 |  7 |  2 |  5 |
|  3 | 5 | 4 | 6 | 4 | 5 | 2 | 7 | 3 | 1 |  6 |  7 |  2 |
|  4 | 2 | 5 | 4 | 6 | 4 | 5 | 2 | 7 | 3 |  1 |  6 |  7 |
|  5 | 7 | 2 | 5 | 4 | 6 | 4 | 5 | 2 | 7 |  3 |  1 |  6 |
|  6 | 3 | 7 | 2 | 5 | 4 | 6 | 4 | 5 | 2 |  7 |  3 |  1 |
|  7 | 1 | 3 | 7 | 2 | 5 | 4 | 6 | 4 | 5 |  2 |  7 |  3 |
|  8 | 6 | 1 | 3 | 7 | 2 | 5 | 4 | 6 | 4 |  5 |  2 |  7 |
|  9 | 7 | 6 | 1 | 3 | 7 | 2 | 5 | 4 | 6 |  4 |  5 |  2 |
| 10 | 2 | 7 | 6 | 1 | 3 | 7 | 2 | 5 | 4 |  6 |  4 |  5 |
| 11 | 5 | 2 | 7 | 6 | 1 | 3 | 7 | 2 | 5 |  4 |  6 |  4 |
| 12 | 6 | 5 | 2 | 7 | 6 | 1 | 3 | 7 | 2 |  5 |  4 |  6 |
+----+---+---+---+---+---+---+---+---+---+----+----+----+

Есть таблица с результатами, вот ее структура:

create table result_schema (
    user_id bigint not null,
    result_1 integer not null,
    result_2 integer not null,
    result_3 integer not null,
    result_4 integer not null,
    result_5 integer not null
);

Столбцы «result_ *» содержат номер столбца из массива.Мне нужно написать функцию для расчета очков.Аргументы функции: значение из столбца result_ * и некоторое ссылочное значение (порядковый номер строки в массиве)

Точки должны быть рассчитаны для каждого поля result_ * и суммированы, а результат отсортирован по убываниюпорядок.

На данный момент я написал функцию:

CREATE OR REPLACE FUNCTION rank(row integer, column integer) RETURNS integer AS $$
DECLARE
    diagonal_number integer;
BEGIN
    diagonal_number = row - column + 1;
    if (diagonal_number < 1) then
        diagonal_number = abs(diagonal_number) + 2;
    end if;

    case diagonal_number
        when 1, 12  then return 6;
        when 2      then return 4;
        when 3, 11  then return 5;
        when 4, 10  then return 2;
        when 5, 9   then return 7;
        when 6, 8   then return 3;
        when 7      then return 1;
        else
            return 0; -- ERROR!
    end case;
END; $$
LANGUAGE PLPGSQL;

А вот запрос для извлечения данных:

select user_id, (
    rank(6, result_1) +
    rank(1, result_2) +
    rank(4, result_3) +
    rank(8, result_4) +
    rank(9, result_5)
) as rate 
from result_schema 
where user_id between 1 and 1000 
order by rate desc;

Есть 5 000 000 элементов втаблица с результатами, но выборка проходит только 1000 каждый.И это занимает ~ 700 мс.Есть ли способ оптимизировать выбор или ускорить поиск другими способами?Можно ли использовать другую СУБД вместо postgres?

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