Соедините 4 таблицы с группировкой, 2 с и где - PullRequest
0 голосов
/ 10 декабря 2018

У меня база данных состоит из 4 таблиц:

  1. пользователей (id, "имя", фамилия, дата рождения)
  2. дружеских отношений (userid1, userid2, "timestamp")
  3. записей (id, идентификатор пользователя, «текст», «отметка времени»)
  4. лайков (postid, идентификатор пользователя, «отметка времени»)

Мне нужен результатнабор уникальных имен пользователей, имеющих более 3 друзей в течение января 2018 года, и их «лайки» в среднем за «пост» в диапазоне [10;35).

Я написал это утверждение для первого шага:

select  distinct u."name"
from users u
join friendships f on u.id = f.userid1
where f."timestamp" between '2018-01-01'::timestamp and '2018-01-31'::timestamp
group by u.id
having count(f.userid1) > 3;

Он работает нормально и возвращает 3 строки.Но когда я добавляю вторую часть следующим образом:

select  distinct u."name"
from users u
join friendships f on u.id = f.userid1
join posts p on p.userid = u.id
join likes l on p.id = l.postid
where f."timestamp" between '2018-01-01'::timestamp and '2018-01-31'::timestamp
group by u.id
having count(f.userid1) > 3 
    and ((count(l.postid) / count(distinct l.postid)) >= 10 
        and (count(l.postid) / count(distinct l.postid)) < 35);

, я схожу с ума по 94 строкам.Я не знаю почему.Буду благодарен за возможную помощь.

Ответы [ 2 ]

0 голосов
/ 10 декабря 2018

Вам не нужно distinct в u.name, потому что агрегат удалит дубликат.

select
   u."name"
from 
   users u
   inner join friendships f on u.id = f.userid1
   inner join posts p on u.id = p.userid
   inner join likes l on p.id = l.postid
where 
   f."timestamp" >= '2018-01-01'::timestamp 
   and f."timestamp" < '2018-02-01'::timestamp
group by 
    u."name"
having 
    count(distinct f.userid1) > 3 
    and ((count(l.postid) / count(distinct l.postid)) >= 10 
            and (count(l.postid) / count(distinct l.postid)) < 35);

Как указано в комментарии.Не очень хорошая идея, когда вы используете between для date для диапазона.

f."timestamp" >= '2018-01-01'::timestamp 
and f."timestamp" < '2018-02-01'::timestamp

Даст вам полный месяц января.

0 голосов
/ 10 декабря 2018

Попробуйте ниже!Проблема с использованием «count (f.userid1)> 3» заключается в том, что если у пользователя, например, 2 друга, 6 постов и 3 лайка, они получат 2 x 6 = 12 строк, поэтому 12 записей с ненулевым f.userid1.Подсчитывая разных f.userid2 вы можете сосчитать разных друзей.Аналогичные проблемы появляются для других счетчиков, используемых для фильтрации.

select  u."name"
from users u
join friendships f on u.id = f.userid1
join posts p on p.userid = u.id
left join likes l on p.id = l.postid
where f."timestamp" > '2018-01-01'::timestamp and f."timestamp" < '2018-02-01'::timestamp
group by u.id, u."name"
having
 --at least three distinct friends
 count( distinct f.userid2) > 3 
  --distinct likes / distinct posts
  --we use l.* to count distinct likes since there's no primary key
  and ((count(distinct l.*) / count(distinct p.id)) >= 10 
        and ((count(distinct l.*) / count(distinct p.id)) < 35);
...