Я недавно боролся с этим вопросом на тесте на работу. У меня есть следующая таблица.

TABLE sessions
   id INTEGER primary key;
   userId INTEGER NOT NULL;
   duration INTEGER NOT NULL;

Мне нужно было написать запрос, который выбирал бы идентификатор пользователя и среднюю продолжительность для каждого пользователя с более чем 1 сеансом. Другими словами, мне нужно было усреднить продолжительность для всех идентификаторов пользователей, которые появлялись в таблице более одного раза. Кто-нибудь может мне с этим помочь?

sql
2
Frank Serkland 17 Фев 2018 в 20:33

1 ответ

Лучший ответ

Вы бы просто использовали предложение having:

select userid, avg(duration)
from sessions
group by userid
having count(*) > 1;

Это был бы "принятый" ответ. Часто самый быстрый подход:

select userid, avg(duration)
from sessions s
where exists (select 1 from sessions s2 where s2.userid = s.userid and s2.id <> s.id)
group by userid;

Это было бы быстрее, если бы многие пользователи работали в одиночку и у вас есть индекс по (userid, id). Почему? Поскольку запрос быстро фильтруется перед агрегацией и значительно сокращает количество строк, ускоряет агрегацию больше, чем стоимость проверки (при данных обстоятельствах).

А в базе данных, которая выполняет целочисленную арифметику, вам может понадобиться avg(duration * 1.0).

Однако кандидат на собеседование пройдет по первому запросу.

11
Gordon Linoff 17 Фев 2018 в 20:33