Столбец подсчета SQL из другой таблицы - PullRequest
0 голосов
/ 26 октября 2019

У меня есть две таблицы в базе данных

Первая - people, в которой есть столбцы

id: int,
name: varchar(10)

, а другая - relationships, представляющая один путь, следующий за

me: int
following: int

Где me и following - внешние ключи, которые соответствуют первичному ключу id для человека в таблице people.

Я хочу выполнить запрос, который дал id человека возвращает его имя и количество людей, за которыми они следуют, и число людей, которые следуют за ним.

Моя текущая попытка

SELECT *, COUNT(following.me), COUNT(following.following) FROM people
WHERE id = 3
JOIN following f1 on f1.me = id
JOIN following f2 on f2.following = id;

Но она выдает ошибкуо синтаксисе где. Я думаю, что мне нужно где-то использовать group by, но я изо всех сил пытаюсь понять, как это работает для нескольких таблиц.

Ответы [ 4 ]

1 голос
/ 26 октября 2019

Ваша попытка не будет работать (даже с правильным синтаксисом), потому что COUNT() возвращает количество ненулевых значений. После JOIN любой столбец без значений NULL будет возвращать тот же результат.

Хотя вы могли бы исправить это с помощью COUNT(DISTINCT), я бы порекомендовал для этого коррелированные подзапросы:

select p.*,
       (select count(*)
        from relationships r
        where r.me = p.id
       ) as num_followed,
       (select count(*)
        from relationships r
        where r.following = p.id
       ) as num_following
from people p;

Вы также можете сделать это с помощью предварительной агрегации:

select p.*, fe.num_followed, fi.num_following
from people p left join
     (select r.me, count(*) as num_followed
      from relationships r
      group by r.me
     ) fe
     on fe.me = p.id left join
     (select r.following, count(*) as num_followed
      from relationships r
      group by r.follwoing
     ) fi
     on fi.following = p.id ;
1 голос
/ 26 октября 2019

Это можно решить просто с помощью встроенных коррелированных подзапросов, например:

select 
    p.name,
    (select count(*) from relationships r where r.following = p.id) followers,
    (select count(*) from relationships r where r.me = p.id) following
from people p
where p.id = 3

Это должно быть достаточно эффективным вариантом.

В противном случае, начиная с существующего запроса, вы также можете left join и совокупность:

select 
    p.name,
    count(distinct r.following) followers,
    count(distinct r.me) following
from people p
left join relationships r on p.id in (r.followers, r.me)
where p.id = 2
group by p.id, p.name
0 голосов
/ 26 октября 2019

Group by id, name двойное соединение таблицы people с таблицей relationships и подсчет различных me и following:

SELECT p.id, p.name,
  COUNT(DISTINCT f1.following) counterfollowers, 
  COUNT(DISTINCT f2.me) counterfollowing
FROM people p
LEFT JOIN relationships f1 on f1.me = p.id
LEFT JOIN relationships f2 on f2.following = p.id
WHERE p.id = 3
GROUP BY p.id, p.name

См. Демонстрационную версию . Результаты:

> id | name | counterfollowers | counterfollowing
> -: | :--- | ---------------: | ---------------:
>  3 | c    |                2 |                1
0 голосов
/ 26 октября 2019

Мы можем попытаться использовать два отдельных подзапроса, чтобы найти два следующих числа:

SELECT
    p.name,
    COALESCE(r1.me_cnt, 0) AS following,
    COALESCE(r2.following_cnt, 0) AS followers
FROM people p
LEFT JOIN
(
    SELECT me, COUNT(*) AS me_cnt
    FROM relationships
    GROUP BY me
) r1
    ON r1.me = p.id
LEFT JOIN
(
    SELECT following, COUNT(*) AS following_cnt
    FROM relationships
    GROUP BY following
) r2
    ON r2.following = p.id;
...