Я получил очень ценный урок от эксперта по SQL очень давно.
Не позволяйте тому, что у вас есть, ослепить вас к тому, что вам нужно . Подумайте, где в реальном мире используются бронирования.
- отели
- Авиакомпании
- Круизные лайнеры
- Аренас
- Футбольные стадионы
Каждый из них имеет фиксированный перечень мест в определенный день. Каждое из этих мест может быть либо открытым, либо зарезервированным - привязанным к конкретному клиенту.
У вас есть фиксированный инвентарь предметов в определенный день. Каждый из этих предметов может быть доступен или зарезервирован - привязан к конкретному клиенту.
Я думаю, что ваша жизнь была бы намного проще, если бы вы создали таблицу доступности, а не таблицу бронирования.
create table availability (
sku varchar(15) not null,
sn varchar(15) not null,
av_date date not null,
customer_id integer, --references customers (customer_id)
primary key (sku, sn, av_date),
foreign key (sku, sn) references items (sku, sn)
);
insert into availability values
('1', '1', '2011-01-01', 1), -- reserved by customer_id 1
('1', '1', '2011-01-02', 1),
('1', '1', '2011-01-03', 1),
('1', '1', '2011-01-04', NULL), -- not yet reserved
('1', '1', '2011-01-05', NULL),
('1', '1', '2011-01-06', NULL),
('1', '1', '2011-01-07', NULL),
('1', '1', '2011-01-08', NULL),
('1', '1', '2011-01-09', NULL),
('1', '1', '2011-01-10', NULL),
('1', '2', '2011-01-01', NULL),
('1', '2', '2011-01-02', 2),
('1', '2', '2011-01-03', 2),
('1', '2', '2011-01-04', 3),
('1', '2', '2011-01-05', 3),
('1', '2', '2011-01-06', NULL),
('1', '2', '2011-01-07', NULL),
('1', '2', '2011-01-08', NULL),
('1', '2', '2011-01-09', NULL),
('1', '2', '2011-01-10', NULL);
(Для производства я бы собрал хранимую процедуру для заполнения таблицы доступности.)
Теперь просто выбрать самую раннюю доступную дату для данного sku.
select sku, sn, av_date, customer_id
from availability
where sku = '1' and customer_id is null
order by av_date asc
limit 1