Обьединение 3х таблиц и агрегация

165
29 июня 2018, 18:30

Есть 3 таблицы - общага, комнаты и студенты.

Определенные комнаты привязаны до "общаги" (через HostelCode)

Студенты привязаны до таблицы "комнаты", в которой есть поле "вместимость студентов" - capacity.

Нужно вывести количество свободных мест в общаге. Нашел как вычислить общее количество, но как мне его использовать? Вот запрос:

Select  Sum(Rooms.Capacity) AS Rooms
From Rooms
WHERE Rooms.HostelCode=1
Answer 1

Можно так

SELECT SUM(Capacity) as AllC, c as Busy, (SUM(Capacity) - c) as Free from Rooms as Ro
INNER JOIN
(select Count(*) as c, r.RoomId as room
from Student as s
inner join Rooms as r On r.RoomId=s.RoomId && r.HostelCode=1
 ) as T On true 
 WHERE HostelCode=1

Ссылка на рабочий пример: http://sqlfiddle.com/#!9/16f2ab/3

Либо со вложенным запросом получается еще несколько короче:

SELECT SUM(Capacity) - (select Count(*)
from Student as s
inner join Rooms as r On r.RoomId=s.RoomId && r.HostelCode=1) 
from Rooms
WHERE HostelCode=1;

Ссылка на рабочий пример: http://sqlfiddle.com/#!9/16f2ab/7

Answer 2

Ответ на вопрос в заголовке: начиная с mySQL 8 появилась конструкция With, которая позволяет разбить текст SQL-запроса на логические части.

например,

with HostelCapacity (
    Select HostelCode, RoomId, sum(Rooms.Capacity) AS Capacity
    From Rooms
    group by HostelCode, RoomId
),
RoomsOccupied (
    Select HostelCode, Student.RoomId, count(*) as Occupied
    From Student
    Left join Rooms on (Student.roomid = rooms.roomId)
    Group by HostelCode, RoomId
),
RoomsRemain (
    select HostelCode, roomId, Capacity as Rooms from HostelCapacity 
    union
    select HostelCode, roomId, -Occupied as Rooms from RoomsOccupied
)
select HostelCode, roomId, sum(rooms) from RoomsRemain
where HostelCode = 1
group by HostelCode, roomId

При всей кажущейся неэффективности запроса, движок сделает нормальный план и вполне оптимально выполнит запрос как единое целое. Но при этом человеку гораздо легче воспринимать отдельные части запроса. а главное в таком запросе четко выделяются повторно-используемые части запроса, текст которых вы можете использовать в других запросах. А также очень четко выделяются части, которые движок может распаралеллить.

Answer 3

Довольно глупый но работающий пример.

declare @HostCode int = 1;
Select  Sum(Rooms.Capacity)-(Select COUNT(*)
    From Student inner join Rooms on Rooms.RoomId=Student.StudentId
    inner join Hostel on Hostel.HostelCode=Rooms.HostelCode
    Where Hostel.HostelCode Like @HostCode)
 AS Rooms
From Rooms
WHERE Rooms.HostelCode Like @HostCode
READ ALSO
Ошибка при подключении MySQL в NetBeans

Ошибка при подключении MySQL в NetBeans

Подскажите в чем причина данной ошибки? Выдавало ошибку: Authentication plugin 'caching_sha2_password' cannot be loaded сделалследующее: Вылезла другая:

175
Cannot make non static method yii\base\Model::rules() static in class app\models\User

Cannot make non static method yii\base\Model::rules() static in class app\models\User

помогите пожалуйста, при входе на страницу регистрации выходит ошибка:

221
как удалить значение поля в таблице mysql если заранее не известно в каком именно поле оно хранится

как удалить значение поля в таблице mysql если заранее не известно в каком именно поле оно хранится

имеется таблица mysql со столбцами id1 id2 id3 в одном из них есть значение userid, как удалить значение userid из ячейки столбца если заранее не известно...

140
Как вывести ошибки нескольких интупов с типом file в laravel?

Как вывести ошибки нескольких интупов с типом file в laravel?

У меня есть от 1 до 10 <input name="photo[]" type="file">"

190