下面是说明,其中包括条件以及我要修改的代码。我需要在下面的代码中添加此条件,但我无法这样做,需要一些帮助。
/hello
如果在物业A预订了8/1至8/2的预订,而在物业A进行了第二预订8/2至8/3的预订,则会员不得赚取多个积分。这是在同一家酒店内,因此从结帐到下次入住之间没有24小时。
如果在物业A预订了8/1至8/2的预订,而在物业B进行了8/2至8/3的第二预订,则会员应获得多个积分。这是在另一个酒店内,因此时间无关紧要。
视觉示例:
whatever()
这是我的代码:
/hello/showForm
数据如下所示,每个LoyaltyMemberid唯一满足上述规则的2个唯一预订号将获得积分。并非所有符合条件的预订都将获得积分。
showForm()
答案 0 :(得分:1)
如果我对您的理解正确,那么您要说明的是,如果自从上次结帐以来已经过去了24小时,那么该会员就有资格获得某种信用。
我要指出的第一件事是您提供的示例数据不一致。
Property A – check in 8/4 to 8/5 - qualified
这有资格获得信用,因为从08/03的上一次“结帐”起经过了整整一天。
但随后您说:
Property C – check in 8/30 to 9/15 – non qualified
在完全相同的情况下,属性A符合条件怎么办?
无论如何,我继续前进,也许这是出于监督。我认为这是一个示例,它将使您朝正确的方向前进以完成所需的工作。
您可以在SSMS中运行以下示例:
DECLARE @data TABLE ( [member] VARCHAR(10), [hotel] VARCHAR(10), [check_in] DATETIME, [check_out] DATETIME );
INSERT INTO @data (
[member], [hotel], [check_in], [check_out]
)
VALUES
( '60135522', 'PropA', '08/01/2018', '08/02/2018' )
, ( '60135522', 'PropA', '08/02/2018', '08/03/2018' )
, ( '60135522', 'PropA', '08/04/2018', '08/05/2018' )
, ( '60135522', 'PropB', '08/05/2018', '08/06/2018' )
, ( '60135522', 'PropC', '08/06/2018', '08/29/2018' )
, ( '60135522', 'PropC', '08/30/2018', '09/15/2018' );
SELECT
MemberStays.member
, MemberStays.hotel
, MemberStays.PrevCheckOut
, MemberStays.CheckIn
, MemberStays.CheckOut
, DATEDIFF( DD, [PrevCheckOut], [CheckIn] ) PrevCheckoutDays
, CASE DATEDIFF( DD, [PrevCheckOut], [CheckIn] )
WHEN 0 THEN 'non qualified'
ELSE 'qualified'
END AS [CreditStatus]
FROM (
SELECT
data1.member
, data1.hotel
, CONVERT(
VARCHAR(10)
, LAG( [check_out], 1, NULL ) OVER ( PARTITION BY [member], [hotel] ORDER BY [member], [hotel], [check_in] )
, 101
) AS PrevCheckOut
, CONVERT( VARCHAR(10), data1.check_in, 101 ) AS CheckIn
, CONVERT( VARCHAR(10), data1.check_out, 101 ) AS CheckOut
FROM @data AS data1
) AS MemberStays
ORDER BY
[hotel], [CheckIn];
返回
+----------+-------+--------------+------------+------------+------------------+---------------+
| member | hotel | PrevCheckOut | CheckIn | CheckOut | PrevCheckoutDays | CreditStatus |
+----------+-------+--------------+------------+------------+------------------+---------------+
| 60135522 | PropA | NULL | 08/01/2018 | 08/02/2018 | NULL | qualified |
| 60135522 | PropA | 08/02/2018 | 08/02/2018 | 08/03/2018 | 0 | non qualified |
| 60135522 | PropA | 08/03/2018 | 08/04/2018 | 08/05/2018 | 1 | qualified |
| 60135522 | PropB | NULL | 08/05/2018 | 08/06/2018 | NULL | qualified |
| 60135522 | PropC | NULL | 08/06/2018 | 08/29/2018 | NULL | qualified |
| 60135522 | PropC | 08/29/2018 | 08/30/2018 | 09/15/2018 | 1 | qualified |
+----------+-------+--------------+------------+------------+------------------+---------------+
我将主要逻辑分解为一个表子查询,以使其易于查看。此处的关键是使用SQL Server的LAG功能(及其分区/排序功能)来查看会员在给定酒店住宿的先前结帐。有了它之后,就可以将其与当前行的CheckIn进行比较,以确定两者之间经过了多少时间。从那里开始变得简单。如果经过的天数是0(零),则它不符合连续学分的条件,否则,则没有资格。
在这里,属性C的第二个记录使我失望。如果我要采用您声明的逻辑,则属性C的记录均符合条件。
已更新以反映指定的新结果
我已经更新了示例,以使用结果集中的更新数据。您可以在SSMS中运行此代码以供审核。
-- replicate resultset definition --
DECLARE @resultset TABLE (
LoyaltyMemberID VARCHAR(10)
, MemberEmail VARCHAR(100)
, PropertyCode VARCHAR(10)
, TotalRevenue DECIMAL(18, 2)
, MarketSubSegment VARCHAR(2)
, RoomNights INT
, RateType VARCHAR(10)
, ReservationNumber VARCHAR(10)
, StayStatus VARCHAR(10)
, rlhc_HotelStatusName VARCHAR(10)
, ArrivalDate SMALLDATETIME
, DepartureDate SMALLDATETIME
);
-- insert sample data into @resultset --
INSERT INTO @resultset (
LoyaltyMemberID, MemberEmail, PropertyCode, TotalRevenue, MarketSubSegment, RoomNights, RateType, ReservationNumber, StayStatus, rlhc_HotelStatusName, ArrivalDate, DepartureDate
) VALUES
( '102282482', 'ljbirr@aol.com', 'WAFEDW', 118.8, 'PR', 1, 'EXT1', '88676', 'R', 'Active', '7/30/2018', '7/31/2018' )
, ( '102282482', 'ljbirr@aol.com', 'ORPEND', 285.6, 'BR', 3, 'WEB', '119223', 'R', 'Active', '7/30/2018', '8/2/2018' )
, ( '102296283', 'tj711@aol.com', 'WAPOUL', 246, 'PR', 3, 'FDR', '975372', 'R', 'Active', '7/30/2018', '8/2/2018' )
, ( '102898784', 'JW@gmail.com', 'WAANGE', 900.9, 'BR', 4, 'RNR', '33401155', 'R', 'Active', '7/30/2018', '8/3/2018' )
, ( '102898784', 'JW@gmail.com', 'WAANGE', 937.4, 'BR', 4, 'RNR', '33401170', 'R', 'Active', '7/30/2018', '8/3/2018' )
, ( '103723804', 'hmayfield@co.net', 'IDCANY', 85.48, 'PR', 1, 'EX1HR', '168702', 'R', 'Active', '7/30/2018', '7/31/2018' )
, ( '103723804', 'hmayfield@co.net', 'WAKENT', 499.75, 'IN', 4, 'EX1', '100803', 'R', 'Active', '7/30/2018', '8/3/2018' )
, ( '104157546', 'dfa@pn.com', 'CAPERR', 89.38, 'BR', 1, 'EX1', '71220', 'R', 'Active', '7/30/2018', '7/31/2018' )
, ( '104337973', 'ralphog@eoni.com', 'ORPEND', 160, 'BR', 2, 'WEB', '119221', 'R', 'Active', '7/30/2018', '8/1/2018' )
, ( '104408813', 'dennisvaughn@msn.com', 'PAHARR', 218, 'IN', 2, 'GRPNP', '164701', 'R', 'Active', '7/30/2018', '8/1/2018' )
, ( '104420433', 'mahlerkelsey@me.com', 'WAFEDW', 245.1, 'C0', 2, 'RNR', '87476', 'R', 'Active', '7/30/2018', '8/1/2018' )
, ( '104420433', 'mahlerkelsey@me.com', 'WAFEDW', 118.8, 'C0', 1, 'EXT1', '88676', 'R', 'Active', '7/30/2018', '7/31/2018' );
然后...
/*
SELECT data from @resultset with the following rules:
- Any stay less than 24 hours does *not* qualify for loyalty credits.
- Only 2 unique reservation numbers per LoyaltyMemberid satisfying the above rule will be given credits.
- Note: Not all reservations that qualify will get credits.
*/
SELECT
LoyaltyMemberID
, MemberEmail
, PropertyCode
, TotalRevenue
, MarketSubSegment
, RoomNights
, RateType
, ReservationNumber
, StayStatus
, rlhc_HotelStatusName
, ArrivalDate
, DepartureDate
, PrevDeparture
, DepartureSeq
-- apply business rules --
, CASE
WHEN ( DATEDIFF( DD, ArrivalDate, PrevDeparture ) = 0 ) THEN 'Not Eligible'
WHEN ( DepartureSeq > 1 ) THEN 'Not Eligible'
ELSE 'Eligible'
END AS CreditEligible
FROM (
-- perform some intital work on the base resultsel --
SELECT
MemberStays.LoyaltyMemberID
, MemberStays.MemberEmail
, MemberStays.PropertyCode
, MemberStays.TotalRevenue
, MemberStays.MarketSubSegment
, MemberStays.RoomNights
, MemberStays.RateType
, MemberStays. ReservationNumber
, MemberStays.StayStatus
, MemberStays.rlhc_HotelStatusName
, CONVERT( VARCHAR(10), MemberStays.ArrivalDate, 101) AS ArrivalDate
, CONVERT( VARCHAR(10), MemberStays.DepartureDate, 101) AS DepartureDate
, CONVERT(
VARCHAR(10),
LAG( MemberStays.DepartureDate, 1, NULL ) OVER (
PARTITION BY MemberStays.LoyaltyMemberID, MemberStays.PropertyCode, MemberStays.ReservationNumber
ORDER BY MemberStays.LoyaltyMemberID, MemberStays.PropertyCode, MemberStays.ReservationNumber, MemberStays.ArrivalDate
)
, 101
) AS PrevDeparture
, ROW_NUMBER() OVER (
PARTITION BY MemberStays.LoyaltyMemberID, MemberStays.PropertyCode, MemberStays.ReservationNumber
ORDER BY MemberStays.LoyaltyMemberID, MemberStays.PropertyCode, MemberStays.ReservationNumber, MemberStays.ArrivalDate
) AS DepartureSeq
FROM @resultset AS MemberStays
) AS LoyaltyData
ORDER BY
LoyaltyData.LoyaltyMemberID, LoyaltyData.PropertyCode, LoyaltyData.ReservationNumber, LoyaltyData.ArrivalDate;
返回
+-----------------+----------------------+--------------+--------------+------------------+------------+----------+-------------------+------------+----------------------+-------------+---------------+---------------+--------------+----------------+
| LoyaltyMemberID | MemberEmail | PropertyCode | TotalRevenue | MarketSubSegment | RoomNights | RateType | ReservationNumber | StayStatus | rlhc_HotelStatusName | ArrivalDate | DepartureDate | PrevDeparture | DepartureSeq | CreditEligible |
+-----------------+----------------------+--------------+--------------+------------------+------------+----------+-------------------+------------+----------------------+-------------+---------------+---------------+--------------+----------------+
| 102282482 | ljbirr@aol.com | ORPEND | 285.60 | BR | 3 | WEB | 119223 | R | Active | 07/30/2018 | 08/02/2018 | NULL | 1 | Eligible |
| 102282482 | ljbirr@aol.com | WAFEDW | 118.80 | PR | 1 | EXT1 | 88676 | R | Active | 07/30/2018 | 07/31/2018 | NULL | 1 | Eligible |
| 102296283 | tj711@aol.com | WAPOUL | 246.00 | PR | 3 | FDR | 975372 | R | Active | 07/30/2018 | 08/02/2018 | NULL | 1 | Eligible |
| 102898784 | JW@gmail.com | WAANGE | 900.90 | BR | 4 | RNR | 33401155 | R | Active | 07/30/2018 | 08/03/2018 | NULL | 1 | Eligible |
| 102898784 | JW@gmail.com | WAANGE | 937.40 | BR | 4 | RNR | 33401170 | R | Active | 07/30/2018 | 08/03/2018 | NULL | 1 | Eligible |
| 103723804 | hmayfield@co.net | IDCANY | 85.48 | PR | 1 | EX1HR | 168702 | R | Active | 07/30/2018 | 07/31/2018 | NULL | 1 | Eligible |
| 103723804 | hmayfield@co.net | WAKENT | 499.75 | IN | 4 | EX1 | 100803 | R | Active | 07/30/2018 | 08/03/2018 | NULL | 1 | Eligible |
| 104157546 | dfa@pn.com | CAPERR | 89.38 | BR | 1 | EX1 | 71220 | R | Active | 07/30/2018 | 07/31/2018 | NULL | 1 | Eligible |
| 104337973 | ralphog@eoni.com | ORPEND | 160.00 | BR | 2 | WEB | 119221 | R | Active | 07/30/2018 | 08/01/2018 | NULL | 1 | Eligible |
| 104408813 | dennisvaughn@msn.com | PAHARR | 218.00 | IN | 2 | GRPNP | 164701 | R | Active | 07/30/2018 | 08/01/2018 | NULL | 1 | Eligible |
| 104420433 | mahlerkelsey@me.com | WAFEDW | 245.10 | C0 | 2 | RNR | 87476 | R | Active | 07/30/2018 | 08/01/2018 | NULL | 1 | Eligible |
| 104420433 | mahlerkelsey@me.com | WAFEDW | 118.80 | C0 | 1 | EXT1 | 88676 | R | Active | 07/30/2018 | 07/31/2018 | NULL | 1 | Eligible |
+-----------------+----------------------+--------------+--------------+------------------+------------+----------+-------------------+------------+----------------------+-------------+---------------+---------------+--------------+----------------+
请记住,我无法针对您的数据库进行测试,但是我的想法是,如果将上述SQL修改为:
SELECT
* -- I didn't feel like typing out all the column names again, however you should as it is a best practice
, CASE
WHEN ( DATEDIFF( DD, ArrivalDate, PrevDeparture ) = 0 ) THEN 'Not Eligible'
WHEN ( DepartureSeq > 1 ) THEN 'Not Eligible'
ELSE 'Eligible'
END AS CreditEligible
FROM (
SELECT
LP.LoyaltyMemberID
, LP.MemberEmail
, H.pcode AS PropertyCode
, CS.TotalRevenue
, CDC.MarketSubSegment
, CS.RoomNights
, CS.RateType
, CS.ReservationNumber
, CS.StayStatus
, H.HotelStatus
, CAST( CS.departuredate AS SMALLDATETIME ) AS DepartureDate
, CAST( CS.ArrivalDate AS SMALLDATETIME ) AS ArrivalDate
, CONVERT(
VARCHAR(10),
LAG( MemberStays.DepartureDate, 1, NULL ) OVER (
PARTITION BY MemberStays.LoyaltyMemberID, MemberStays.PropertyCode, MemberStays.ReservationNumber
ORDER BY MemberStays.LoyaltyMemberID, MemberStays.PropertyCode, MemberStays.ReservationNumber, MemberStays.ArrivalDate
)
, 101
) AS PrevDeparture
, ROW_NUMBER() OVER (
PARTITION BY MemberStays.LoyaltyMemberID, MemberStays.PropertyCode, MemberStays.ReservationNumber
ORDER BY MemberStays.LoyaltyMemberID, MemberStays.PropertyCode, MemberStays.ReservationNumber, MemberStays.ArrivalDate
) AS DepartureSeq
FROM ODS.C_DCustomerStay AS CS
LEFT OUTER JOIN [ODS].[MemberTransactions] AS CDC
ON CDC.SourceReferenceNumber = CS.ReservationNumber
LEFT JOIN [ODS].[Memberships] AS LP
ON LP.profileID = CDC.profileID
LEFT OUTER JOIN dbo.[Hotels] AS H
ON CS.CPropertyID = H.cidcode
WHERE
CAST( ArrivalDate AS DATE ) = DATEADD( DD, -1, GETDATE() ) --extracting records for yesterday
AND NULLIF( LoyaltyMemberID, '' ) IS NOT NULL
AND RoomNights >= 1 -- Min room nights > 1
AND CAST(totalrevenue AS FLOAT) >= 1 -- Min Revenue >= 1
AND DATEDIFF( DD, arrivaldate, departuredate ) >= 1
) AS LoyaltyInfo
ORDER BY
LoyaltyMemberID, PropertyCode, ReservationNumber, ArrivalDate;
它应该根据我从最初的问题中收集到的信息为您提供所需的信息。
注释对:
我缩短了
AND LoyaltyMemberID <> '' AND LoyaltyMemberID IS NOT NULL
到
AND NULLIF( LoyaltyMemberID, '' ) IS NOT NULL
使用更少的代码即可完成相同的工作。
我改变了
CAST(ArrivalDate AS DATE) = DATEADD(day, -1, CONVERT(DATE, GETDATE()))
到
CAST( ArrivalDate AS DATE ) = DATEADD( DD, -1, GETDATE() )
您不需要转换GETDATE()。已经是约会了。
案例...
WHEN ( DepartureSeq > 1 ) THEN 'Not Eligible'
将同一预订中的所有后续住宿都排除在信用额之外。
思想夫妇:
»您似乎对#33401156的数据有重复的保留。我已出于演示目的将其删除。
»您为什么要设定到达和离开的日期?它们不是您数据库中的日期列吗?
»您应该读一本书或研究有关SQL Best Practices的一些在线培训。我会直言不讳:您的SQL充满了别名不一致,(可能的)数据类型问题和大小写敏感性不一致的问题。改善这一点将大大有助于简化以后的代码重构过程。
P.S。添加
, ( '102898784', 'JW@gmail.com', 'WAANGE', 225.23, 'BR', 4, 'RNR', '33401155', 'R', 'Active', '08/03/2018', '8/4/2018' )
插入@resultset中的值将向您展示规则集中“不合格”的工作方式。