Загрузка данных


CREATE DATABASE Airport;
GO

USE Airport;
GO

CREATE TABLE Cities
(
    Id   INT IDENTITY(1,1) PRIMARY KEY,   -- автоматический номер
    Name NVARCHAR(50) NOT NULL            -- название города
);

-- Рейсы самолетов, из нашенского
CREATE TABLE Flights
(
    Id             INT IDENTITY(1,1) PRIMARY KEY,
    FlightNumber   NVARCHAR(10) NOT NULL,  -- номер рейса
    CityId         INT NOT NULL,           -- куда летит 
    DepartureTime  DATETIME NOT NULL,      -- время вылета
    ArrivalTime    DATETIME NOT NULL,      -- время прилета
    BusinessSeats  INT NOT NULL,           -- всего мест в бизнес классе
    EconomySeats   INT NOT NULL,           -- всего мест в эконом классе
    FOREIGN KEY (CityId) REFERENCES Cities(Id)
);

-- Пассажиры
CREATE TABLE Passengers
(
    Id         INT IDENTITY(1,1) PRIMARY KEY,
    FirstName  NVARCHAR(50) NOT NULL,
    LastName   NVARCHAR(50) NOT NULL,
    Passport   NVARCHAR(20) NOT NULL       -- номер паспорта
);
CREATE TABLE Tickets
(
    Id          INT IDENTITY(1,1) PRIMARY KEY,
    FlightId    INT NOT NULL,              -- на какой рейс билет
    PassengerId INT NOT NULL,              -- кто купил
    Class       NVARCHAR(10) NOT NULL,     -- 'Business' или 'Economy'
    Price       MONEY NOT NULL,            -- цена билета
    SaleDate    DATE NOT NULL,             -- дата продажи
    FOREIGN KEY (FlightId)    REFERENCES Flights(Id),
    FOREIGN KEY (PassengerId) REFERENCES Passengers(Id),
    CHECK (Class IN ('Business', 'Economy'))  -- других классов быть не может
);
GO


-- Города (у Мадрида рейсов не будет)
INSERT INTO Cities (Name) VALUES
(N'Лондон'),   -- Id = 1
(N'Париж'),    -- Id = 2
(N'Берлин'),   -- Id = 3
(N'Рим'),      -- Id = 4
(N'Мадрид');   -- Id = 5

-- Берем сегодняшнюю дату, чтобы запросы на сегодня всегда что-то показывали
DECLARE @today DATETIME = CAST(CAST(GETDATE() AS DATE) AS DATETIME);

-- Рейсы: (номер, город, вылет, прилет, бизнес-мест, эконом-мест)
INSERT INTO Flights (FlightNumber, CityId, DepartureTime, ArrivalTime, BusinessSeats, EconomySeats) VALUES
('SU101', 1, DATEADD(HOUR, 9,  @today),      DATEADD(MINUTE, 9*60+150, @today),      2, 5),  -- сегодня, Лондон, 2.5 часа
('SU102', 2, DATEADD(HOUR, 14, @today),      DATEADD(MINUTE, 14*60+110, @today),     2, 5),  -- сегодня, Париж, 1ч 50м
('SU103', 1, DATEADD(HOUR, 32, @today),      DATEADD(MINUTE, 32*60+150, @today),     2, 5),  -- завтра, Лондон
('SU104', 3, DATEADD(HOUR, 36, @today),      DATEADD(MINUTE, 36*60+90, @today),      2, 5),  -- завтра, Берлин, 1.5 часа
('SU105', 4, DATEADD(HOUR, 55, @today),      DATEADD(MINUTE, 55*60+180, @today),     2, 5),  -- послезавтра, Рим, 3 часа
('SU106', 2, DATEADD(HOUR, 66, @today),      DATEADD(MINUTE, 66*60+110, @today),     2, 5),  -- послезавтра, Париж
('SU107', 1, DATEADD(HOUR, 82, @today),      DATEADD(MINUTE, 82*60+150, @today),     2, 5),  -- через 3 дня, Лондон
('SU108', 3, DATEADD(HOUR, 88, @today),      DATEADD(MINUTE, 88*60+90, @today),      2, 5);  -- через 3 дня, Берлин

-- Пассажиры
INSERT INTO Passengers (FirstName, LastName, Passport) VALUES
(N'Иван',   N'Петров',   'AB100001'),
(N'Анна',   N'Смирнова', 'AB100002'),
(N'Олег',   N'Кузнецов', 'AB100003'),
(N'Мария',  N'Попова',   'AB100004'),
(N'Сергей', N'Иванов',   'AB100005'),
(N'Елена',  N'Волкова',  'AB100006');

-- Билеты: (рейс, пассажир, класс, цена, дата продажи)
DECLARE @d DATE = CAST(GETDATE() AS DATE);   -- сегодня как дата (без времени)

INSERT INTO Tickets (FlightId, PassengerId, Class, Price, SaleDate) VALUES
(1, 1, 'Business', 500, @d),                    -- SU101: оба бизнес-места проданы
(1, 2, 'Business', 500, @d),
(1, 3, 'Economy',  200, DATEADD(DAY, -1, @d)),
(2, 4, 'Business', 450, @d),                    -- SU102: 1 из 2 бизнес-мест занято
(2, 5, 'Economy',  180, DATEADD(DAY, -1, @d)),
(3, 6, 'Economy',  210, @d),
(3, 1, 'Business', 520, DATEADD(DAY, -1, @d)),
(4, 2, 'Economy',  150, @d),
(5, 3, 'Business', 600, @d),
(5, 4, 'Economy',  300, DATEADD(DAY, -2, @d)),
(6, 5, 'Economy',  190, @d),
(7, 6, 'Economy',  220, DATEADD(DAY, -1, @d));
GO


-- Все рейсы в определенный город, дате, по времени
DECLARE @city NVARCHAR(50) = N'Лондон';
DECLARE @date DATE = CAST(GETDATE() AS DATE);   -- можно подставить любую дату

SELECT F.FlightNumber, C.Name AS City, F.DepartureTime
FROM Flights AS F
JOIN Cities AS C ON C.Id = F.CityId             -- присоединяем название города
WHERE C.Name = @city
  AND CAST(F.DepartureTime AS DATE) = @date     -- отрезаем время, оставляем дату
ORDER BY F.DepartureTime;                       -- сортировка по времени вылета
GO

-- Рейс с наибольшей длительностью полета
-- Используем ALL из урока: длительность >= длительности ВСЕХ рейсов
SELECT FlightNumber, DepartureTime, ArrivalTime,
       DATEDIFF(MINUTE, DepartureTime, ArrivalTime) AS DurationMinutes
FROM Flights
WHERE DATEDIFF(MINUTE, DepartureTime, ArrivalTime) >= ALL
      (SELECT DATEDIFF(MINUTE, DepartureTime, ArrivalTime)
       FROM Flights);
GO

-- Все рейсы, где полет длится больше двух часов
SELECT FlightNumber, DepartureTime, ArrivalTime,
       DATEDIFF(MINUTE, DepartureTime, ArrivalTime) AS DurationMinutes
FROM Flights
WHERE DATEDIFF(MINUTE, DepartureTime, ArrivalTime) > 120;
GO

-- Количество рейсов в каждый город
SELECT C.Name AS City, COUNT(F.Id) AS FlightsCount
FROM Cities AS C
LEFT JOIN Flights AS F ON F.CityId = C.Id       -- LEFT, чтобы города без рейсов тоже были (будет 0)
GROUP BY C.Name;
GO

-- Город, в который летают чаще всего
-- если несколько городов с одинаковым максимумом, покажет все
SELECT TOP 1 WITH TIES C.Name AS City, COUNT(*) AS FlightsCount
FROM Flights AS F
JOIN Cities AS C ON C.Id = F.CityId
GROUP BY C.Name
ORDER BY COUNT(*) DESC;                         -- самый частый - первый
GO

-- Рейсы по городам + общее количество за месяц
DECLARE @month INT = MONTH(GETDATE());          -- нужный месяц
DECLARE @year  INT = YEAR(GETDATE());

SELECT C.Name AS City, COUNT(*) AS FlightsCount
FROM Flights AS F
JOIN Cities AS C ON C.Id = F.CityId
WHERE MONTH(F.DepartureTime) = @month AND YEAR(F.DepartureTime) = @year
GROUP BY C.Name
UNION ALL                                       -- добавляем итоговую строку
SELECT N'ВСЕГО', COUNT(*)
FROM Flights
WHERE MONTH(DepartureTime) = @month AND YEAR(DepartureTime) = @year;
GO

-- Рейсы, вылетающие сегодня, где еще есть свободные места в бизнес классе
SELECT F.FlightNumber, F.DepartureTime,
       F.BusinessSeats - COUNT(T.Id) AS FreeBusinessSeats   -- всего мест минус проданные
FROM Flights AS F
LEFT JOIN Tickets AS T
       ON T.FlightId = F.Id AND T.Class = 'Business'        -- считаем только бизнес-билеты
WHERE CAST(F.DepartureTime AS DATE) = CAST(GETDATE() AS DATE)
GROUP BY F.FlightNumber, F.DepartureTime, F.BusinessSeats
HAVING COUNT(T.Id) < F.BusinessSeats;                       -- проданных меньше, чем мест
GO

-- Количемитво проданных билетов и общая сумма за указанный день
DECLARE @saleDay DATE = CAST(GETDATE() AS DATE);

SELECT COUNT(*) AS TicketsSold,
       SUM(Price) AS TotalSum
FROM Tickets
WHERE SaleDate = @saleDay;
GO

-- предварительная продажа: все рейсы на дату и сколько на них продано билетов
DECLARE @flightDay DATE = DATEADD(DAY, 1, CAST(GETDATE() AS DATE));  -- например, завтра

SELECT F.FlightNumber, F.DepartureTime, COUNT(T.Id) AS TicketsSold
FROM Flights AS F
LEFT JOIN Tickets AS T ON T.FlightId = F.Id     -- чтобы рейсы без билетов тоже были
WHERE CAST(F.DepartureTime AS DATE) = @flightDay
GROUP BY F.FlightNumber, F.DepartureTime;
GO

-- номера всех рейсов и названия всех городов
-- города без рейсов (Мадрид) покажутся с нул в номере рейса
SELECT F.FlightNumber, C.Name AS City
FROM Cities AS C
LEFT JOIN Flights AS F ON F.CityId = C.Id
ORDER BY C.Name;
GO