Хитрый запрос MySQL

[Удален]
771

Столкнулся с проблемой.

Есть 4 таблицы

#users {id,login,pass,type}

#students {id,name,group}

#teachers {id,name,duty}

#groups {id,title}

Суть в том что в users лежат логины и пароли юзеров для входа в систему. Юзеры бывают двух типов - студенты и преподы. Причем у них разный набор полей, но у обоих есть имя. Эти доп. параметры лежат соответственно в таблицах students и teachers (связь по id, он не автоинкрементный а по особым правилам формируется). У студентов есть еще группа, название хранится в таблице groups связь по id группы.

Собственно, нужно извлечь все эти данные разом, со столбцом "ФИО", т.е. чтобы у преподов туда втыкалось из одной таблицы, а у студентов из другой. Плюс еще группа.

Короче у меня получилось это сделать так


SELECT `users`. * , IF( `users`.`type` =1,
CONCAT_WS( ' ', `teachers`.`surname` , `teachers`.`name` , `teachers`.`patronymic` ) , CONCAT_WS( ' ', `students`.`surname` , `students`.`name` , `students`.`patronymic` ) ) AS `name` , `group` , `title`
FROM `users`
LEFT JOIN `students` ON `users`.`id` = `students`.`id`
LEFT JOIN `teachers` ON `users`.`id` = `teachers`.`id`
LEFT JOIN `groups` ON `groups`.`id` = `students`.`group`
ORDER BY `group` DESC , `name`

Вроде все круто, только вот мне нужен Right Join в обоих случаях, т.е. у некоторых студентов и преподов может не быть логина. Если поменять left на right будет столько же строчек, заполненных NULLами

Т.е. мне нужно извлечь список всех студентов и преподов в одну колонку, плюс прикрепить доп.поля по ситуации, и если есть в users подходящая запись, то еще и оттуда поля.

Подскажите, как такое решить.

[Удален]
#1

Возможно сделать из

#users {id,login,pass,type}

#students {id,name,group}

#teachers {id,name,duty}

одну таблицу

#users {id,login,pass,type,group/duty}

V1
На сайте с 30.03.2006
Offline
52
#2
neolord:


Вроде все круто, только вот мне нужен Right Join в обоих случаях, т.е. у некоторых студентов и преподов может не быть логина. Если поменять left на right будет столько же строчек, заполненных NULLами

Так и должно быть. Он же присоединяет какую-либо из таблиц students или teachers

тут стоит использовать union all

что-то вроде:

SELECT name

from users u

inner join students s on s.id=u.id

union all

SELECT name

from users u

inner join teachers s on t.id=u.id

[Удален]
#3
claygod:
Возможно сделать из

#users {id,login,pass,type}
#students {id,name,group}
#teachers {id,name,duty}

одну таблицу

#users {id,login,pass,type,group/duty}

Базу нельзя менять.

Vladimir1:
Так и должно быть. Он же присоединяет какую-либо из таблиц students или teachers

тут стоит использовать union all
что-то вроде:
SELECT name
from users u
inner join students s on s.id=u.id
union all
SELECT name
from users u
inner join teachers s on t.id=u.id

Почти так и сделал.


SELECT `users`. * , `t1`.`name` AS `name` , `t1`.`duty` AS `duty`,`group`, `groups`.`title` AS `title`
FROM (
SELECT `id` , CONCAT_WS( ' ', `surname` , `name` , `patronymic` ) AS `name` , `duty`,'0' as `group`
FROM `teachers`
UNION SELECT `id` , CONCAT_WS( ' ', `surname` , `name` , `patronymic` ) AS `name` , 'студент',`group`
FROM `students`
) AS t1
LEFT JOIN `users` ON `users`.`id` = `t1`.`id`
LEFT JOIN `groups` ON `t1`.`group` = `groups`.`id`
ORDER BY `group` DESC,`name`
V1
На сайте с 30.03.2006
Offline
52
#4

Использовать надо union all: во-первых, работает быстрее; во-вторых, дубли вам все равно не нужно отбрасывать (если конечно нет студентов приписанных к учителям и состоящих в группе "студенты").

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий