PostgreSQL: СУММА двух значений из age

#sql #postgresql #sum #aggregate-functions #date-arithmetic

#sql #postgresql #сумма #агрегатные функции #дата-арифметика

Вопрос:

Я пытаюсь СУММИРОВАТЬ два значения, которые вычисляются с использованием функции AGE в PostgreSQL. ВОЗРАСТ должен быть рассчитан как МАКСИМАЛЬНОЕ и МИНИМАЛЬНОЕ значения, связанные с различными (сеансовыми) значениями из этого столбца (значения сеанса различны). Функция AGE должна извлекать минуты из столбца (date_time), а затем также часы из (date_time) и умножать это значение на 60, а затем суммировать эти значения вместе для общего количества минут для сеанса.

Я смог успешно сделать это с

 SELECT 
session, organization, username,
((date_part('hour',age(MAX(date_time), Min(date_time)))*60)   date_part('minute',age(MAX(date_time),
Min(date_time)))) AS Duration
FROM 
analysis.user_activity
enter code here
  

Однако теперь я пытаюсь упорядочить ПО СУММЕ числа, которое возвращает эта функция, на основе СУММЫ продолжительности по ГРУППЕ (организации), просто выполняя заказы ORDER BY (Duration) по наибольшему единичному значению, вычисленному выше, а не всю агрегацию по группе. Вот тут-то и начинаются проблемы. Сначала я попробовал следующим образом:

 SELECT
SUM(
(date_part('hour',age(MAX(date_time), Min(date_time)))*60),
date_part('minute',age(MAX(date_time), Min(date_time)))) as SumofDuration
FROM
analysis.user_activity
  

и я получаю эту ошибку: ОШИБКА: функция sum (двойная точность, двойная точность) не существует Подсказка: ни одна функция не соответствует заданному имени и типам аргументов. Возможно, вам потребуется добавить явные приведения типов. Позиция: 137. Я также получал ошибки о том, что вы не можете вложить агрегатные функции, и поэтому я разделил свой ВЫБОР на несколько шагов, и теперь у меня есть следующее.

 SELECT
session, organization, username,
SUM((SELECT date_part('hour',age(MAX(date_time), Min(date_time)))::integer*60
FROM analysis.user_activity)
, 
(SELECT date_part('minute',age(MAX(date_time), Min(date_time)))::integer
FROM analysis.user_activity))
  

ИЗ
analysis.user_activity

Однако это также выдает ошибку ОШИБКА: функция sum(integer, integer) не существует Подсказка: ни одна функция не соответствует заданному имени и типам аргументов. Возможно, вам потребуется добавить явные приведения типов. Позиция: 169. Я также пробовал это с типом numeric. Согласно документации https://www.postgresql.org/docs/8.2/functions-aggregate.html , это ДОЛЖНО быть в состоянии СУММИРОВАТЬ любой из трех типов данных, которые выдает моя функция. Так что же не так?

Заранее спасибо.

Ответ №1:

Я думаю, вы слишком усложняете ситуацию. Если я правильно понимаю, вы можете просто сделать:

 select session, organization, username,
    extract(epoch from max(date_time) - min(date_time)) / 60 duration_minutes
from analysis.user_activity
group by session, organization, username
  

Обоснование: max(date_time) - min(date_time) дает вам интервал; вы можете использовать extract with epoch , чтобы преобразовать его в количество секунд, затем разделить результат на 60 , чтобы преобразовать его в минуты.

Обратите внимание, что я также исправил запрос агрегации, в котором отсутствовало group by предложение. Если вы хотите суммировать продолжительность всех сеансов, добавьте еще один уровень агрегирования:

 select sum(duration_seconds) / 60 total_duration_minutes
from (
    select extract(epoch from max(date_time) - min(date_time)) duration_seconds
    from analysis.user_activity
    group by session, organization, username
) t
  

Комментарии:

1. большое вам спасибо за быстрый ответ. Я новичок в PostgreSQL, и его необычная операция, связанная со временем и датой, заставляет меня вращать колеса. Ваше решение отлично сработало, еще раз спасибо.