#sql #postgresql
#sql #postgresql
Вопрос:
У меня есть таблица с образцами данных; table
email_id | sender_id | received_id |email_cnt
1 | 101 | 102 | t1
2 | 101 | 103 | t2
3 | 102 | 103 | t3
4 | 103 | 104 | t4
Вот email_id
уникальный идентификатор. Цель состоит в том, чтобы найти cnt электронной почты для каждого пользователя. Как мы можем видеть, всего email_cnt t1 t2 t3 t4.
, и у нас есть 4 уникальных пользователя. Следовательно, в конце концов, мы должны быть в состоянии получить (t1 t2 t3 t4)/4
в качестве ответа.
Моя идея состоит в том, чтобы сначала определить вызывающего абонента, который также является получателем.
SELECT tab1.receiver_id,
tab1.email_cnt AS received,
tab2.sender_id,
tab2.email_cnt AS made
FROM table tab1
JOIN table tab2
ON tab1.receiver_id=tab2.caller_id;
Это дает следующий результат;
receiver_id | received |sender_id | made
102 | t1 | 102 | t3
103 | t2 | 103 | t4
103 | t3 | 103 | t4
Проблема в том, что значение t4
повторяется из-за объединения здесь. Позже это может привести к чрезмерному подсчету email_cnt. Могу ли я любезно получить информацию о том, как решить эту проблему? спасибо
Ответ №1:
Это кажется немного сложным. Но вы можете сделать:
select max(total_duration) * 1.0 / count(distinct v.id)
from (select t.*, sum(call_duration) over () as total_duration
from t
) t cross join lateral
(values (caller_id), (receiver_id)) v(id);
Вот скрипка db<> .
Ответ №2:
Это может сработать, но вам может потребоваться выполнить sum(Made) / count(distinct caller_ID), чтобы получить среднее значение для вызывающего абонента
здесь было бы полезно левое соединение и использование следующих агрегатов sum amp; count
SELECT tab1.receiver_id,
--tab1.call_duration AS received,
sum(tab2.call_duration) / count(distinct tab2.caller_id) as Made
FROM table tab1
left JOIN table tab2
ON tab1.receiver_id=tab2.caller_id
group by
tab1.receiver_id,
tab1.call_duration;
это также приведет к появлению дополнительной строки, но длительность комментария составит 1 результат для каждого клиента
Ответ №3:
Возможно, я неправильно истолковываю, но кажется, что и получатель, и вызывающий абонент являются клиентами, и вы хотели бы, чтобы клиент вызывал индивидуальную длину вызова независимо от того, является ли он получателем или вызывающим абонентом?
Я предлагаю использовать объединение, которое удалит повторяющиеся вызовы, т.Е. Будет работать с уникальными вызовами для каждого клиента, а затем вы сможете усреднить продолжительность
WITH CTE AS (
SELECT
call_id,
receiver_id as customer_id,
call_duration
FROM table
UNION
SELECT
call_id,
caller_id as customer_id,
call_duration
FROM table
)
SELECT
AVG(call_duration) AS AVG_CallDuration,
COUNT(call_id) AS TotalCalls,
customer_id
FROM CTE
GROUP BY customer_id
Комментарии:
1. Ценю ваш ответ. На самом деле, то, что я ищу, — это одно число, среднее время звонка, затраченное на одного клиента. Но этот запрос выдает таблицу. спасибо за помощь.
Ответ №4:
Чтобы вычислить среднее время, затраченное на одного клиента, вы можете
select sum(call_duration) / count(distinct receiver_id)
from yourtable;
Если я неправильно понял проблему, пожалуйста, дайте мне знать.
Редактировать
Оказывается, что вызывающий и получатель оба являются клиентами. Итак
select sum(call_duration) / (count(distinct receiver_id) count(distinct caller_id) - (select count(distinct mt1.caller_id) from mytable mt1 join mytable mt2 on mt1.caller_id = mt2.receiver_id))
from mytable;
Комментарии:
1. Ценю ваше. ответ, но он исключит
101
, кто является вызывающим, следовательно, клиентом. Есть ли способ включить это также? спасибо