Запись, связанная со всеми записями другой таблицы в SQL.

StackOverflow https://stackoverflow.com/questions/3277290

  •  17-09-2020
  •  | 
  •  

Вопрос

Допустим, у нас есть три таблицы в реляционной базе данных:

Person {id, name}
Obstacle {id, name}
Person_overcomes_obstacle {person_id, obstacle_id}

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

Это было полезно?

Решение

Я замечаю, что я был единственным человеком, чтобы использовать природную таблицу псевдоним для Person_overcomes_obstacle!

Вам нужен Реляционный дивизион Запрос для этого.

Вы можете либо подсчитать препятствия, а соответствующие записи в Person_overComes_obstacle и возвращаемые, где 2 числа совпадают или посмотрите на него другой способ, находящиеся в поисках людей, для которых нет препятствий, которые они не преодолевают.

SELECT p.id, p.name /*Or use COUNT(*) or wrap in Exists 
                     if you don't care about ids and names*/
FROM Person p
WHERE NOT EXISTS
   (SELECT * FROM Obstacle o
    WHERE NOT EXISTS 
    (
       SELECT * FROM Person_overcomes_obstacle poo
       WHERE poo.person_id = p.id and o.id = poo.obstacle_id
    )
)
.

Другие советы

SELECT 
    p.name,
    COUNT(DISTINCT oo.obstacle_id) AS OBSTACLES_COMPLETED
FROM 
    person p

    JOIN person_overcomes_obstacle oo
    ON oo.person_id = p.person_id

GROUP BY 
    p.name

HAVING 
    COUNT(DISTINCT poo.obstacle_id) = (SELECT COUNT(id) FROM obstacle)
.

Использовать:

SELECT poo.person_id
    FROM PERSON_OVERCOMES_OBSTACLE poo
GROUP BY poo.person_id
    HAVING COUNT(DISTINCT poo.obstacle_id) = (SELECT COUNT(*) 
                                                                        FROM OBSTACLE)

Это альтернатива, которая с меньшей вероятностью будет работать хорошо:

SELECT x.person_id
   FROM (SELECT poo.person_id,
                         COUNT(DISTINCT poo.obstacle_id) AS obs_overcome,
                         (SELECT COUNT(*) 
                             FROM OBSTACLE) AS obs_total
                 FROM PERSON_OVERCOMES_OBSTALCE poo
          GROUP BY poo.person_id) x
 WHERE x.obs_overcome = x.obs_total

В любом случае вы можете присоединиться к таблице PERSON, чтобы получить дополнительную информацию, если хотите, или вы можете выполнить подсчет person_id из любого запроса, чтобы узнать, сколько человек преодолело все записанные препятствия.

Этот выбор должен вернуть количество препятствий, которые никто не преодолел.Если счет равен нулю, то все препятствия были преодолены хотя бы одним человеком.

SELECT count(*)
  FROM (SELECT po.person_id, o.obstacle_id
          FROM Obstacle o
          LEFT OUTER JOIN Person_overcomes_obstacle po
            ON (o.obstacle_id = po.obstacle_id)) t
WHERE t.person_id IS NULL
.

Вы также можете сделать это, для того же эффекта (и, возможно, лучшую производительность):

SELECT count(*)
  FROM Obstacle o
 WHERE NOT EXISTS (SELECT 1
                     FROM Person_overcomes_obstacle po
                    WHERE po.obstacle_id = o.obstacle_id)
.

Редактировать: Как указано в комментариях, вышеприведенные два запроса только доказывают, что нет препятствий, которые никто не преодолел, а не тот человек преодолел все препятствия.

Это кроме того, должно быть возможно, доказать, что один пользователь преодолел все препятствия без Запрос таблицы человека:

SELECT t.personid, count(*)
  FROM (SELECT DISTINCT po.person_id, o.obstacle_id
          FROM Obstacle o
          JOIN Person_overcomes_obstacle po
            ON (o.obstacle_id = po.obstacle_id)) t
 GROUP BY t.persion_id
 HAVING count(*) = (SELECT count(*)
                      FROM obstacle)
.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top