尝试创建报告,以查看存储单元在1个租约和另一个租赁之间空置的时间。信息存储在客户表中,其中包含以下列:
PK (Customer Code) | Storage_Number (FK) | Status | startdate | enddate
我获得了基本代码,用于寻找每个单位的MAX
(最后)客户以及之前的1位客户。我的问题是存储单元目前是空置的。它将显示New Customer Start Date
过去的客户,而我希望此字段为空,Prior Customer End Date
应来自最近的客户。
Select s.PK [Storage Number],
ca.enddate [Prior Customer End Date],
cb.startdate [New Customer Start Date],
Datediff(DAY, ca.enddate, cb.startdate)-1 [Days Vacant]
From Storage s
Left Outer Join (
Select Storage_Number,
MAX(PK) Customer_Code
FROM Customer
WHERE Status in (‘Future’, ‘Active’, ’Past’)
Group By Storage_Number
)maxa On maxa.Storage_Number = s.PK
Left Outer Join(
Select Storage_Number,
MAX(PK) Customer_Code
FROM Customer b
Full Outer Join (
Select Storage_Number sn,
MAX(PK) cc
FROM Customer
WHERE Status in (‘Future’, ‘Active’, ’Past’)
Group By Storage_Number
)a on a.sn = b.Storage_Number
WHERE Status in (‘Future’, ‘Active’, ’Past’)
And b.PK != a.cc
Group by Storage_Number
)maxb
ON maxb.Storage_Number = s.PK
Left Outer Join Customer ca on ca.Storage_Number = s.PK and ca.PK = maxb.PK
Left Outer Join Customer cb on cb.Storage_Number = s.PK and cb.PK = maxa.PK
WHERE ca.enddate !> cb.startdate
Order By ca.enddate
我可以添加多个CASE
语句
Select s.PK [Storage Number],
CASE
WHEN cb.status = ‘Past’
THEN cb.enddate
Else ca.enddate
END [Prior Customer End Date],
CASE
WHEN cb.status = ‘Past’
THEN null
ELSE cb.startdate
END [New Customer Start Date],
CASE
WHEN cb.status = ‘Past’
THEN null
ELSE Datediff(DAY, ca.enddate, cb.startdate)-1
END [Days Vacant]
FROM ………..
但是我想看看是否有更好的方法来做到这一点。
答案 0 :(得分:1)
<强>更新强>
SQL 2000版本(使用下面的设置代码/我没有经过测试,因为没有SQL 2000实例;希望所有内容都与该版本兼容,因为我没试过使用任何太现代的东西。)
declare @firstAvailableDate datetime = '2014-12-20' --allows us to see how many days the units were available before their first booking
, @lastAvailableDate datetime = getutcdate() --allows us to say up to which date we're interested for the last booking
declare @BookingSequence table
(
OrderByStorageId bigint identity(1,1)
, StorageId bigint
, StartDate datetime
, EndDate datetime
, CustomerId bigint
)
insert @BookingSequence
select StorageId, StartDate, EndDate, CustomerId
from @CustomerBookings
order by StorageId, StartDate
declare @BookingPrevAndCurrent table
(
StorageId bigint
, StartDate datetime
, EndDate datetime
, PreviousBookingEndDate datetime
, CustomerId bigint
, OrderByStorageId bigint
)
insert @BookingPrevAndCurrent
select c.StorageId, c.StartDate, c.EndDate, coalesce(p.EndDate,@firstAvailableDate), c.CustomerId, c.OrderByStorageId
from @BookingSequence c
left outer join @BookingSequence p
on p.StorageId = c.StorageId
and p.OrderByStorageId = c.OrderByStorageId - 1
select s.Name StorageUnit
, c.Name Customer
, x.PreviousBookingEndDate
, coalesce(x.StartDate, @lastAvailableDate) CurrentBookingStartDate
, DateDiff(Day,x.PreviousBookingEndDate, coalesce(x.StartDate, @lastAvailableDate)) DaysBetweenBookings
from @Storage s
left outer join @BookingPrevAndCurrent x
on x.StorageId = s.id
left outer join @Customer c
on c.id = x.CustomerId
order by StorageUnit, PreviousBookingEndDate
SQL 2008版本
尝试这样的事情:
--setup code / sample data
declare @CustomerBookings table
(
Id bigint identity(1,1)
, CustomerId bigint
, StorageId bigint
, StatusId int
, StartDate datetime
, EndDate datetime
)
declare @Storage table
(
id bigint identity(1,1)
, Name nvarchar(32) not null
)
declare @Customer table
(
id bigint identity(1,1)
, Name nvarchar(32) not null
)
insert @Storage values('A'),('B'),('C')
insert @Customer values('Jane'),('Paul'),('Keith')
insert @CustomerBookings
select c.id, s.id, 1, x.b, x.e
from
(
select 'Jane' c, 'A' s, '2015-01-01' b, '2015-01-03' e
union all
select 'Jane' c, 'A' s, '2015-01-05' b, '2015-01-06' e
union all
select 'Jane' c, 'B' s, '2015-01-05' b, '2015-01-06' e
union all
select 'Paul' c, 'C' s, '2015-01-02' b, '2015-01-06' e
union all
select 'Paul' c, 'A' s, '2015-01-07' b, '2015-01-10' e
union all
select 'Paul' c, 'A' s, '2015-01-012' b, '2015-01-18' e
union all
select 'Keith' c, 'B' s, '2015-01-01' b, '2015-01-04' e
union all
select 'Keith' c, 'A' s, '2015-01-20' b, '2015-01-23' e
union all
select 'Keith' c, 'B' s, '2015-01-08' b, '2015-01-10' e
union all
select 'Keith' c, 'B' s, '2015-01-20' b, '2015-01-23' e
) x
inner join @Storage s on s.Name = x.s
inner join @Customer c on c.Name = x.c
--the actual solution
declare @firstAvailableDate datetime = '2014-12-20' --allows us to see how many days the units were available before their first booking
, @lastAvailableDate datetime = getutcdate() --allows us to say up to which date we're interested for the last booking
;with BookingSequence as
(
select StorageId, StartDate, EndDate, CustomerId, ROW_NUMBER() over (partition by StorageId order by StartDate) OrderByStorageId
from @CustomerBookings
)
, BookingPrevAndCurrent as
(
select StorageId, StartDate, EndDate, @firstAvailableDate PreviousBookingEndDate, CustomerId, OrderByStorageId
from BookingSequence c
where c.OrderByStorageId = 1
union all
select c.StorageId, c.StartDate, c.EndDate, p.EndDate, c.CustomerId, c.OrderByStorageId
from BookingPrevAndCurrent p
inner join BookingSequence c
on c.StorageId = p.StorageId
and c.OrderByStorageId = p.OrderByStorageId + 1
)
select s.Name StorageUnit
, c.Name Customer
, x.PreviousBookingEndDate
, coalesce(x.StartDate, @lastAvailableDate) CurrentBookingStartDate
, DateDiff(Day,x.PreviousBookingEndDate, coalesce(x.StartDate, @lastAvailableDate)) DaysBetweenBookings
from @Storage s
left outer join BookingPrevAndCurrent x
on x.StorageId = s.id
left outer join @Customer c
on c.id = x.CustomerId
order by StorageUnit, PreviousBookingEndDate