有趣的问题。为了让这更容易理解,我将使用一个临时表来说明可能的解决方案。如果它对您有效,并且您不希望表出现在那里,那么您应该能够稍微折叠查询。以下是我想知道的关于每个预订的信息:
declare @RegistrationDetail table
(
RegistrationId int,
CustomerId varchar(5),
AdultsIncluded int,
ChildrenIncluded int,
AdultsRemaining int,
ChildrenRemaining int
);
前两个字段将直接从
dbo.Registrations
桌子
AdultsIncluded
和
ChildrenIncluded
将分别给出每个保留地上已经出现的成年人和儿童的总数。
AdultsRemaining
和
ChildrenRemaining
将分别给出保留地中仍可能增加的成人和儿童人数,而无需支付额外费用。因此,对于完整注册,剩余计数将为2减去已使用的预订数量,而对于基本预订,剩余计数将始终为零。
with GuestCountCTE as
(
select
Reg.RegistrationId,
AdultsIncluded = 1 + sum(case when Guest.GuestType in ('Adult Included', 'Additional Adult') then 1 else 0 end),
ChildrenIncluded = sum(case when Guest.GuestType in ('Child Included', 'Additional Child') then 1 else 0 end)
from
dbo.Registrations Reg
left join dbo.RegistrationAdditionalGuestDetails Guest on Reg.RegistrationId = Guest.RegistrationId
group by
Reg.RegistrationId
)
insert @RegistrationDetail
select
Reg.RegistrationId,
Reg.customerId,
GCount.AdultsIncluded,
GCount.ChildrenIncluded,
AdultsRemaining = case when Reg.RegistrationType = 'Full' and GCount.AdultsIncluded < 2 then 2 - GCount.AdultsIncluded else 0 end,
ChildrenRemaining = case when Reg.RegistrationType = 'Full' and GCount.ChildrenIncluded < 2 then 2 - GCount.ChildrenIncluded else 0 end
from
dbo.Registrations Reg
inner join GuestCountCTE GCount on Reg.RegistrationId = GCount.RegistrationId;
CTE建立已使用的预订数量,以及
INSERT
下面的语句直接从CTE获取数据,然后推断出剩余的保留数量。这里需要注意以下几点:
-
你当然可以在没有CTE的情况下做到这一点。我使用了一个,只是为了进一步细分该方法,避免编写表达式
成人包括在内
和
包括儿童
每次两次。
-
我在这里假设,如果没有使用“包含成人”的完整注册,或者没有使用“包含儿童”的完整注册,就不会有“包含其他成人”的完整注册。如果不是这样,那么尽管整体方法仍然有效,您需要更明智地确定每个预订中剩余的可用空间。
-
请注意
1
添加到
成人包括在内
表示这代表了首先注册的成年人。
这是我现在的数据
@RegistrationDetail
:
RegistrationId CustomerId AdultsIncluded ChildrenIncluded AdultsRemaining ChildrenRemaining
1 00001 1 0 0 0
2 00001 2 2 0 0
3 00001 1 2 1 0
4 00002 3 3 0 0
5 00002 1 1 1 1
6 00003 2 1 0 0
7 00003 2 2 0 0
因此,现在我需要的是至少有一个预订的任何客户的标识符,其中出现在该预订上的成人和儿童数量小于或等于该客户所有
另外
保留。这其实并不难:
with RemaindersByCustomerCTE as
(
select
Detail.CustomerId,
AdultsRemaining = sum(Detail.AdultsRemaining),
ChildrenRemaining = sum(Detail.ChildrenRemaining)
from
@RegistrationDetail Detail
group by
Detail.CustomerId
)
select
Rem.CustomerId
from
RemaindersByCustomerCTE Rem
where
exists
(
select 1
from
@RegistrationDetail Detail
where
Detail.AdultsIncluded <= (Rem.AdultsRemaining - Detail.AdultsRemaining) and
Detail.ChildrenIncluded <= (Rem.ChildrenRemaining - Detail.ChildrenRemaining)
);
在这里,我首先使用CTE生成一个结果集,其中每个客户都有一条记录,以及每个客户上未使用的成人和儿童空间的总数
全部的
他们的保留。CTE产生:
CustomerId AdultsRemaining ChildrenRemaining
00001 1 0
00002 1 1
00003 0 0
最后,CTE后的位使用半连接(即
EXISTS
)仅返回
CustomerId
具有符合上述标准的注册的值。特别注意
WHERE
这个查询中的子句:我不能简单地写
Detail.AdultsIncluded <= Rem.AdultsRemaining
因为
Rem.AdultsRemaining
是否有成人空间
全部的
客户的预订,包括
Detail
这样,客户就无法通过将客人从一个登记处转移到同一登记处的空白处来节省资金。最终结果集为:
CustomerId
00001
00002
这看起来对你有用吗?