Как мне получить значение из следующей записи с условием WHERE в SQL?

Я создал представление SQL с помощью Management Studio. Представление объединяет несколько таблиц вместе и доступно для моего приложения MVC. Таблицы относятся к аренде автомобилей. Одна таблица содержит сведения об автомобиле, а другая - информацию о бронировании, которые объединяются с помощью представления.

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

Таблица: Автомобили

  • [Идентификатор]
  • [Регистрация]
  • [Делать]
  • [Модель]

Таблица: бронирования

  • [Идентификатор]
  • [BookingStartDate]
  • [BookingEndDate]
  • [CarId]

Просмотр: CarBookings

SELECT  [C].[Id],
        [C].[Registration],
        [C].[Make],
        [C].[Model],
        [B].[BookingStartDate],
        [B].[BookingEndDate]

  FROM [Cars] AS C INNER JOIN [Bookings] AS B ON C.Id = B.CarId

Как я могу добавить в свое представление столбец, в котором будет отображаться следующее бронирование, которое у машины есть? Любая помощь приветствуется.

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

Tim Biegeleisen 29.08.2018 11:22

Не могли бы вы подробнее рассказать о «следующем немедленном бронировании»? Как работает эта логика? Где это хранится? Какие данные у вас есть на этот случай? Ваш текущий sql должен просто получить все согласованные экземпляры между вашими автомобилями и бронированиями, что означает, что вы также по умолчанию получите «следующее немедленное бронирование» по умолчанию, если оно сохранено в таблице бронирования?

Martin 29.08.2018 11:24

Из вопроса кажется, что вам нужно первое бронирование в текущую дату и время или позже? Если да, то вы можете использовать ВЕРХ или ПРЕДЕЛ с заказом на. Но этот синтаксис скорее зависит от базы данных. Так что вы можете добавить тег для нужного вам типа базы данных.

LukStorms 29.08.2018 11:32

Вы хотите показать только информацию об автомобиле и следующее предстоящее бронирование? (Как уже упоминалось, в вашем текущем запросе в настоящее время отображаются все бронирования, старые и новые)

Magnus 29.08.2018 11:33
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
2
4
610
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Используйте LEAD() (sql server 2012 и новее)

select c.*, b.BookingStartDate, b.BookingEndDate,
       lead(bookingstartdate) over (partition by carid order by BookingStartDate) as nextbooking
from cars c
inner join bookings b
on c.id = b.carid

Мне нравится идея использовать LEAD (если он доступен), но я думаю, вам нужно как-то ограничить свой запрос, чтобы возвращалась только последняя запись о бронировании (в настоящее время он возвращает все).

Tim Biegeleisen 29.08.2018 11:34

Я тоже так думаю, просто пропущена запятая после b.BookingEndDate, и вы имеете в виду BookingEndDate вместо date?

Oto Shavadze 29.08.2018 11:47

@TimBiegeleisen Вопрос неясен по этому поводу, поэтому обеспечивает целостное представление

JohnHC 29.08.2018 11:48

Вот запрос, который должен дать желаемые результаты. В CTE я использую сводный запрос, чтобы получить самую последнюю и вторую по времени запись о бронировании для каждого CarId. Затем мы присоединяем этот CTE к таблице Car аналогично тому, как вы это уже делали.

WITH cte AS (
    SELECT
        CarId,
        MAX(CASE WHEN rn = 1 THEN BookingStartDate END) AS BookingStartDate,
        MAX(CASE WHEN rn = 1 THEN BookingEndDate   END) AS BookingEndDate,
        MAX(CASE WHEN rn = 2 THEN BookingStartDate END) AS NextBookingStartDate,
        MAX(CASE WHEN rn = 2 THEN BookingEndDate   END) AS NextBookingEndDate
    FROM
    (
        SELECT CarId, BookingStartDate, BookingEndDate,
            ROW_NUMBER() OVER (PARTITION BY CarId ORDER BY BookingStartDate DESC) rn
        FROM Bookings
    ) t
    WHERE rn <= 2
    GROUP BY CarId
)

SELECT
    c.Id,
    c.Registration,
    c.Make,
    c.Model,
    b.BookingStartDate,
    b.BookingEndDate,
    b.NextBookingStartDate,
    b.NextBookingEndDate
FROM Cars c
INNER JOIN cte b
    ON c.Id = b.CarId;
Ответ принят как подходящий

Как сказал Тим в комментариях, ваш запрос уже дает вам все бронирования, но если вам нужно в другом столбце, то, возможно, вам нужен lead()?

SELECT  C.Id,
B.BookingStartDate,
B.BookingEndDate,
lead(BookingStartDate) over(partition by C.Id order by B.BookingEndDate) nextdt
FROM Cars AS C INNER JOIN Bookings AS B ON C.Id = B.CarId

Ниже запрос предоставит все предстоящие заказы на конкретный автомобиль. Если вам нужен только следующий, вам следует использовать Row_number.

SELECT  [C].[Id],
        [C].[Registration],
        [C].[Make],
        [C].[Model],
        [B].[BookingStartDate],
        [B].[BookingEndDate]

  FROM [Cars] AS C 
  INNER JOIN [Bookings] AS B ON C.Id = B.CarId
  WHERE [B].[BookingStartDate] >= GETDATE()
  ORDER BY [B].[BookingStartDate]

Если существующее представление делает то, что вы хотите (это все комбинации автомобилей и бронирований, кроме машин без бронирований, так как вы использовали внутреннее соединение), и вы просто хотите спроецировать "следующий" порядок, который, как я предполагаю, ссылается на текущую дату и время,

вы можете добавить левое соединение к запросу, который извлекает «следующее» бронирование для каждой машины и создает столбец, который определяет его, когда оно соответствует следующей записи.

Логика левого соединения:

  1. Получайте все будущие бронирования на машину (это фильтр "Где")
  2. Возьмите следующий (минимальное время бронирования).
  3. Присоединяйтесь - по дате бронирования и carId (теперь, если будет два одинаковых бронирований на машину, вы получите оба в следующем матче, так как присоединитесь к условие будет применяться к обоим).

    select 
    a.* , 
    b.* ,
    case when c.carId is not null then 1 else 0 end as IsNext
    from cars a
    inner join bookings b
        on a.id = b.carid
    left join (select carid , min(bookingStartDate) bookingStartDate from bookings where bookingStartDate > now() group by carid) c
        on b.carId = c.carId
        and b.bookingStartDate = c.bookingStartDate
    

комментарий: этот ответ - синтаксис postgres, поскольку вы не указали, какую базу данных вы используете. если это sql-сервер - замените now () на GETDATE ()

Y.S 29.08.2018 11:42

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