Несколько запросов SQL в одной функции - PullRequest
0 голосов
/ 15 мая 2018

Мне нужно вернуть несколько значений в одном запросе SQL в моей базе данных postgresql. Вот мой запрос:

SELECT AVG("percent"), MIN("percent"), MAX("percent"), AVG("profit"), MIN("profit"), MAX("profit")
FROM public.log_analyticss 
WHERE "buyPlatform" = 'platA' AND
"date" >= '1526356073.6126819'

Данные

date             sellPlatform     profit      percent    
----------       ------------     ----------  ----------
1526356073.61    platA            0           10.1
1526356073.62    platA            22          11
1526356073.63    platA            3           7
1526356073.64    platA            1           8
1526356073.65    platA            11          9
1526356073.66    platA            12          10
1526356073.67    platA            13          15

Желаемый результат

date             sellPlatform     profit      percent    
----------       ------------     ----------  ----------
1526356073.61    platA            0           10.1         //MIN Profit
1526356073.62    platA            22          11           //MAX Profit
1526356073.63    platA            3           7            //MIN Perc
1526356073.67    platA            13          15           //MAX Perc

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

Проблема в том, что я не просто хочу значения MIN и MAX. Я хочу всю строку данных, из которых взято значение MIN и MAX.

Я понимаю, что я запрашиваю AVG и значение MIN / MAX, которое будет возвращать данные в двух разных форматах. Я знаю, что это может быть невозможно. Но любая помощь о том, как наиболее эффективно сделать это, была бы чрезвычайно полезной.

Сейчас я просто вытаскиваю весь набор данных в свой код и вычисляю среднее, минимальное и максимальное значения в моем коде, которые я знаю, если они очень плохие, а также очень и очень медленные. Таблица содержит около 8 миллионов строк, а набор данных, который я собираю, составляет около 9000 строк, поэтому сейчас я делаю это очень медленно.

Ответы [ 3 ]

0 голосов
/ 15 мая 2018

Вам нужно что-то вроде этого:

SELECT a.*
FROM public.log_analyticss  a
JOIN
(
    SELECT 
        MIN("percent") min_percent, 
        MAX("percent") max_percent, 
        MIN("profit") min_profit, 
        MAX("profit") max_profit
    FROM public.log_analyticss 
) t ON a.date = t.date AND
       a.sellPlatform = t.sellPlatform AND
       (a.profit = minprofit OR
        a.profit = maxprofit OR
        a.percent = minpercent OR
        a.percent = maxpercent)
0 голосов
/ 15 мая 2018

Наиболее эффективный способ получения строки, связанной с минимумом / максимумом, обычно вообще не включает агрегаты MIN() / MAX();вместо этого вы можете просто прикрепить ORDER BY к вашему запросу и добавить LIMIT 1, чтобы получить только первую запись.

Это означает, что вам нужно четыре SELECT оператора с четырьмя различными порядками, но вы можетевыделите дорогую часть (выборку из log_analyticss) в временную таблицу или CTE , например:

WITH Data AS (
  SELECT *
  FROM public.log_analyticss 
  WHERE "buyPlatform" = 'platA' AND
    "date" >= '1526356073.6126819'
)
(SELECT 'Min percent', * FROM Data ORDER BY "percent" ASC LIMIT 1)
UNION ALL
(SELECT 'Max percent', * FROM Data ORDER BY "percent" DESC LIMIT 1)
UNION ALL
(SELECT 'Min profit', * FROM Data ORDER BY "profit" ASC LIMIT 1)
UNION ALL
(SELECT 'Max profit', * FROM Data ORDER BY "profit" DESC LIMIT 1)

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

Обратите внимание, что если одно из этих максимальных / минимальных значений совместно используется двумя разными строками, этот запрос вернет только одну изих.Выбранная строка выбирается произвольно, но вы можете присоединить больше полей к предложению ORDER BY, чтобы они служили в качестве разрыва связи.

Если вы действительно хотите обе записи в этом случае, вам понадобится что-тобольше похоже на ответ Остона или Радима, то есть сначала вычислите агрегаты, а затем присоединитесь к данным в столбцах profit и percent.Вы все еще можете использовать временную таблицу / CTE, чтобы избежать повторного нажатия log_analyticss.

0 голосов
/ 15 мая 2018

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

Или вы можете попробовать запустить временную таблицу (автоматически отбрасывается после завершения сеанса):

CREATE TEMP TABLE statistics AS 
    SELECT AVG(percent) as perc_avg, MIN(percent) as perc_avg, MAX(percent) as perc_max, AVG(profit) as pro_avg, MIN(profit) as pro_min, MAX(profit) as pro_max
    FROM public.log_analyticss 
    WHERE buyPlatform = 'platA' AND
    sellPlatform = 'platB' AND 
    productId = '183948' AND
    date >= '1526356073.6126819'
;
    SELECT date, sellPlatform, profit, percent
    FROM public.log_analyticss a join statistics s
     on (a.profit = s.pro_max or a.profit = s.pro_min or
         a.percent = s.perc_max or a.percent = s.perc_min)
    WHERE buyPlatform = 'platA' AND
    sellPlatform = 'platB' AND 
    productId = '183948' AND
    date >= '1526356073.6126819';

Ссылка на временные таблицы: http://www.postgresql.org/docs/9.2/static/sql-createtable.html

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