У меня есть не очень нормализованная таблица:
ItemName Type DateTransferred
Hand Drill IN 2012-01-16 11:06:10.077
Hand Drill OUT 2012-01-16 11:06:16.563
Hand Drill IN 2012-01-16 11:06:26.780
Grinder IN 2012-01-16 11:06:33.917
Hand Drill OUT 2012-01-16 11:06:45.443
Создать запрос:
CREATE TABLE [dbo].[TransferLog](
[ItemName] [nvarchar](50) NOT NULL,
[Type] [nvarchar](3) NOT NULL,
[DateTransferred] [datetime] NOT NULL
) ON [PRIMARY]
ALTER TABLE [dbo].[TransferLog]
ADD CONSTRAINT [DF_TransferLog_DateTransferred]
DEFAULT (getdate()) FOR [DateTransferred]
Как правило, в приведенной выше таблице регистрируются заимствованные элементы (тип: IN) и элементы, возвращенные (тип: OUT) командой проекта со склада.
Чего я хочу добиться, так это получить все заимствованное оборудование, когда оно было заимствовано (IN) и когда оно было возвращено (OUT). Проблема возникает при попытке сопоставить «транзакцию заимствования» с соответствующей «транзакцией возврата», поскольку единственное отношение, которое они имеют, - это ItemName:
Выбор всех «транзакций займа»:
select tIn.ItemName, tIn.DateTransferred as DateBorrowed
from transferLog as tIn
where tIn.[type] = 'IN'
Результат:
ItemName DateBorrowed
Hand Drill 2012-01-16 11:06:10.077
Hand Drill 2012-01-16 11:06:26.780
Grinder 2012-01-16 11:06:33.917
Попытка выбрать все «заимствованные транзакции» и соответствующую им «возвратную транзакцию»:
select tIn.ItemName, tIn.DateTransferred as DateBorrowed,
tOut.DateTransferred as DateReturned
from transferLog as tIn
left join transferLog as tOut
on tIn.ItemName = tOut.ItemName
and tOut.[type] = 'OUT'
where tIn.[type] = 'IN'
Результат:
ItemName DateBorrowed DateReturned
Hand Drill 2012-01-16 11:06:10.077 2012-01-16 11:06:16.563
Hand Drill 2012-01-16 11:06:10.077 2012-01-16 11:06:45.443
Hand Drill 2012-01-16 11:06:26.780 2012-01-16 11:06:16.563
Hand Drill 2012-01-16 11:06:26.780 2012-01-16 11:06:45.443
Grinder 2012-01-16 11:06:33.917 NULL
Обратите внимание, что каждая "заимствованная транзакция" должна иметь только одну или не иметь соответствующей "транзакции возврата", приведенный выше результат сопоставляет каждую "заимствованную транзакцию" с каждой "транзакцией возврата", если они имеют одинаковые ItemName
. Результат должен быть:
ItemName DateBorrowed DateReturned
Hand Drill 2012-01-16 11:06:10.077 2012-01-16 11:06:16.563
Hand Drill 2012-01-16 11:06:26.780 2012-01-16 11:06:45.443
Grinder 2012-01-16 11:06:33.917 NULL
Теперь я подумываю о том, как сопоставить «транзакцию возврата» с DateTransferred
, большим и ближайшим к «транзакции заимствования» DateTransferred. Что-то вроде:
select tIn.ItemName, tIn.DateTransferred as DateBorrowed,
tOut.DateTransferred as DateReturned
from transferLog as tIn
left join transferLog as tOut
on tIn.ItemName = tOut.ItemName
and tOut.[type] = 'OUT'
and
tOut.DateTransferred > tIn.DateTransferred
-- AND NEAREST tOut.DateTransferred TO tIn.DateTransferred
where tIn.[type] = 'IN'
Я читаю это ( SQL Join на Ближайший меньше, чем дата ) и это ( Соединение таблиц на ближайшую дату в прошлом, в MySQL ), но подзапрос - трудный выбор для меня поскольку результат запроса, который мне нужен, является лишь частью другого запроса, боюсь, это повлияет на производительность.