SQL-запрос на 4 таблицы: очень сложный? - PullRequest
0 голосов
/ 26 августа 2011

у меня есть четыре таблицы

alert:
    * monitor_id
    * group_id

group:
    * group_id

user:
    * user_id
    * email

user_group:
    * group_id
    * user_id

возможно ли получить почту пользователя, используя только monitor_id?Если да!это возможно только в одном запросе?Пожалуйста, помогите мне, будь то SQL-запрос или доктрина!

Ответы [ 3 ]

3 голосов
/ 26 августа 2011

Если вы хотите использовать monitor_id для получения электронной почты пользователя, выполните:

SELECT DISTINCT
  u.user_id
  u.email
FROM `user` u
INNER JOIN user_group ug ON u.user_id = ug.user_id 
INNER JOIN `group` g ON ug.group_id = g.group_id 
INNER JOIN alert a ON a.group_id = g.group_id
WHERE a.monitor_id = '1548'

Поскольку путь от monitor_id до user.email проходит через все таблицы, вам понадобятся все эти объединения.
Пока вы проиндексировали (!) Все поля, используемые в соединениях, среда выполнения должна быть быстрой.

3 голосов
/ 26 августа 2011

Правильный запрос:

SELECT DISTINCT user.email FROM user 
inner join user_group on user.user_id=user_group.user_id 
inner join alert on  alert.group_id=user_group.group_id
where alert.monitor_id = provided_monitor_id

Предыдущий запрос с комментариями Шахбаз.

SELECT * FROM user inner join user_group on user.user_id=user_group.user_id 
inner join  group on user_group.group_id=group.group_id inner 
join alert on  alert.group_id=group.group_id
group by user.user_id

Редактирование (Шахбаз): Чтобы объяснить, как работает команда:

Когда у вас есть две таблицы, совместно использующие поле (переменная, если вам нравится), вы можете join две таблицы (также называемые inner join), в результате чего большая таблица объединяет данные из двух таблиц (вы даже можете сделать это)если нет полей для обмена).Давайте рассмотрим это на примере:

Table People: поля: pid, pname, pjob

с записями

  • (0, «Алиса», «Студент»')
  • (1, «Боб», «фабричный рабочий»)
  • (2, «клара», «медсестра»)

Таблица Задания: поля: jname, jpay

с записями

  • («учитель», 1000)
  • («студент», 0)
  • («фабрика»worker ', 2000)

Теперь, если вы скажете People join Jobs, вы получите таблицу с 9 записями, имеющую:

поля: pid, pname, pjob, jname, jpay

с записями

  • (0, 'Алиса', 'студент', 'учитель', 1000)
  • (0, 'Алиса', 'студент', 'студент ', 0)
  • (0,' Алиса ',' студент ',' фабричный рабочий ', 2000)
  • (1,' Боб ',' фабричный рабочий ',' учитель ', 1000)
  • (1, «Боб», «фабричный рабочий», «студент», 0)
  • (1, «Боб», «фабричный рабочий», «фабричный рабочий»,2000)
  • (2, «Клара», «медсестра», «учитель», 1000)
  • (2, «Клара», «медсестра», «студент ', 0)
  • (2,' Клара ',' медсестра ',' фабричный рабочий ', 2000)

Как видите, это не очень хороший стол!Вы можете использовать условие on в join для извлечения информации, относящейся друг к другу.Например, мы можем захотеть увидеть зарплату каждого человека.Следовательно, People.pjob должен быть равен Jobs.jname, поэтому, если вы скажете People join Jobs on People.pjob=Jobs.jname, вы получите таблицу, содержащую:

поля: pid, pname, pjob, jname, jpay

сзаписи

  • (0, «Алиса», «студент», «студент», 0)
  • (1, «Боб», «фабричный рабочий», «фабричный рабочий»,2000)

Обратите внимание, что работа Клары не существует в таблице заданий и, следовательно, ее нет в итоговой таблице.

Хотя inner join предоставляет вам данные из двух таблицэто совпадение, вы можете получить данные таблиц, даже если на другой стороне нет совпадений.Это называется outer join.В этом примере People outer join Jobs возвращает таблицу с полями

: pid, pname, pjob, jname, jpay

с записями

  • (0, "Алиса", «студент», «студент», 0)
  • (1, «Боб», «фабричный рабочий», «фабричный рабочий», 2000)
  • (2, «Клара», «медсестра, null, null)
  • (null, null, null, «учитель», 1000)

Если вы хотите толькоТаблица с левой стороны outer join, которую нужно включить, даже если она не соответствует, используйте left outer join (в этом случае будет присутствовать строка «Клара», а не строка «учитель»).Аналогично, right outer join дает строки из правой таблицы, даже если она не соответствует, но не из левой таблицы.

Наконец, вы уже должны знать, что делает select, он просто возвращает таблицу с выбранными столбцами из предоставленнойстолбец (* выбор всех столбцов).Данная таблица может быть просто именем таблицы или любой другой таблицы, сформированной с помощью команд sql (таблицы, созданные с помощью самой команды select (в этом случае не стесняйтесь использовать скобки), таблицы создаются с помощью команды join и т. Д.).Если вы понимаете эту рекурсивную природу SQL, вы можете создавать команды так сложно, как вам нравится.Просто представьте, что каждая операция над таблицами выдает другую таблицу, которую вы можете просто использовать вместе с другими операциями, как если бы эта таблица была простой именованной таблицей!

0 голосов
/ 26 августа 2011

Другой способ (без использования DISTINCT или GROUP BY):

SELECT 
    u.user_id
  , u.email
FROM `user` AS u
WHERE EXISTS
      ( SELECT *
        FROM alert AS a 
          JOIN `group` AS g
            ON g.group_id = a.group_id 
          JOIN user_group AS ug
            ON ug.group_id = g.group_id
        WHERE ug.user_id = u.user_id 
          AND a.monitor_id = @monitorId      -- the monintor_id to be checked
      ) 

Примечание : не рекомендуется именовать таблицы или поля с ключевыми словами илизарезервированные слова, такие как user и даже хуже group.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...