SQL-запрос для поиска пользователей с приложениями без выпусков - PullRequest
0 голосов
/ 08 октября 2018

В моей базе данных есть пользователи, приложения и релизы.Пользователь может иметь 0..n приложений через таблицу разрешений, а приложение может иметь 0..n выпусков.

Я пытаюсь получить список пользователей, у которых есть хотя бы 1 приложение, но ни одно изу приложений этого пользователя есть какие-либо выпуски.

Схема примерно

users  permissions  apps  releases
-----  -----------  ----  --------
id     user_id      id    id
email  app_id             app_id

Я думаю У меня есть кое-что с этим работать, но это кажется мне неэффективным, потому чтоЯ дважды упоминаю таблицу разрешений и использую вложенные предложения о существовании.Есть ли более эффективный способ написать этот запрос?

select u.email from users u 
    join permissions p on p.user_id = u.id 
    where not exists (
        select a.id from apps a 
            join permissions p on p.app_id = a.id 
            where p.user_id = u.id and exists (
                select r.id from releases r 
                    where r.app_id = a.id
            )
    ); 

Ответы [ 4 ]

0 голосов
/ 08 октября 2018

Вам просто нужно использовать LEFT JOIN в выпусках, а затем искать случай, когда количество выпущенных приложений (r.app_id не NULL) равно 0. Если все, что вам нужно, это список пользователей, яне думайте, что вам вообще нужно JOIN таблицу apps, так как JOIN в permissions обеспечит включение только пользователей, имеющих разрешение на 1 или более приложений.

SELECT u.email
FROM users u
JOIN permissions p ON p.user_id = u.id
LEFT JOIN releases r ON r.app_id = p.app_id
GROUP BY u.email
HAVING COUNT(r.app_id) = 0
0 голосов
/ 08 октября 2018

Еще одна вещь, которую вы можете попробовать - это сочетание левого и внутреннего объединений, например:

Select
    email
From users u
Inner Join (
    Select
        p.user_id
        , p.app_id
     From permissions p
     Left Join releases r
        on p.app_id = r.app_id
     Where r.app_id is null) a
on u.user_id = a.user_id
Group by email

Трудно сказать, что быстрее между этим и предыдущим опубликованным решением, не зная размера различных таблиц.(и, следовательно, сколько строк SQL будет пытаться объединить).

Ясно одно: без строки «Группировать по электронной почте» в конце вы можете видеть, что электронная почта пользователя повторяется несколько раз в вашем списке.Как правило, в литературе по SQL говорится, что использование оператора «group by» в конце вашего запроса является более быстрым способом получения отдельного набора, чем выражение «select Different» в начале вашего запроса.

0 голосов
/ 08 октября 2018

Я сделаю что-то вроде этого, надеюсь, это поможет:

SELECT
    u.id, u.email
FROM
    users AS u
INNER JOIN
    permissions AS p ON p.user_id = u.id
LEFT JOIN
    releases AS r ON r.app_id = p.app_id
GROUP BY
    u.id, u.email
HAVING
    SUM(CASE WHEN r.id IS NOT NULL THEN 1 ELSE 0 END) = 0
0 голосов
/ 08 октября 2018

Первый Join представляется правильным между users и permissions таблицей.Вам просто нужно проверить, существует ли app_id из объединенного набора результатов в таблице releases или нет.Вы можете попробовать этот запрос -

select u.email from users u 
join permissions p on p.user_id = u.id 
where not exists ( Select 1 from releases r where r.App_id = p.app_id)
...