我正在编写一个存储过程来获取基于下表的值。
我根据买家的国籍填写公寓单位。
存储过程必须根据以下规则返回下一个非占用单位:
如果有新的条目,我需要建议与新人相同国籍的被占用单位旁边的非占用单位
如果上述条件未找到匹配项,则在未占用单位的楼层内分配第一个单位
如果上述情况未找到匹配项,则分配一个两侧至少有两个空单位的单位
如果上述条件未找到匹配项,则根据排序顺序分配第一个为空的展位
注意:
每个单位都由Floor& amp;单否
搜索时对于平面和地板的排序顺序应为1到n
示例输入:NAME:RANDY NATIONALITY:BRAZIL
SAMPLE OUTPUT :FLOOR:1 FLAT NO:4(w.r.t.到附图)
答案 0 :(得分:1)
关键是为每个条件创建列,例如,如果下一个房屋所有者具有相同的国籍,则为一列;如果楼层为空,则为一列。
然后,您可以采用所有标准,并将其放置在ROW_NUMBER()
函数的订单中,以按照您定义的顺序获取单位。以下查询中的关键部分是:
RowNumber = ROW_NUMBER() OVER(ORDER BY PrevIsNationalityMatch DESC,
NextIsNationalityMatch DESC,
EmptyFloor DESC,
EmptyFlatsEitherSide DESC,
Floor,
FlatNo)
四列(PrevIsNationalityMatch
,NextIsNationalityMatch
,EmptyFloor', 'EmptyFlatsEitherSide
)都是位字段,因此,如果存在前一个单位由同一国籍的人拥有的行,则总是被ROW_NUMBER函数排名第一,否则它会查找下一个单位是否由同一国籍的人拥有(我添加了这条规则似乎合乎逻辑,但可以通过将其从订单中删除而轻松删除),以及依此类推,直到它只是按地板和平面排序。
DECLARE @NewOwnerNationality VARCHAR(20) = 'BRAZIL';
WITH FlatOwnerNationality AS
( SELECT FlatMaster.Floor,
FlatMaster.FlatNo,
FlatMaster.IsOccupied,
IsNationalityMatch = CASE WHEN OwnerMaster.OwnerNationality = @NewOwnerNationality THEN 1 ELSE 0 END
FROM FlatMaster
LEFT JOIN OwnerMaster
ON OwnerMaster.OwnerName = FlatMaster.OwnerName
), Flats AS
( SELECT FlatMaster.Floor,
FlatMaster.FlatNo,
FlatMaster.IsOccupied,
EmptyFlatsEitherSide = CASE WHEN PrevFlat.IsOccupied = 'NO' AND NextFlat.IsOccupied = 'NO' THEN 1 ELSE 0 END,
EmptyFloor = CASE WHEN COUNT(CASE WHEN FlatMaster.IsOccupied = 'YES' THEN 1 END) OVER(PARTITION BY FlatMaster.Floor) = 0 THEN 1 ELSE 0 END,
PrevIsNationalityMatch = ISNULL(PrevFlat.IsNationalityMatch, 0),
NextIsNationalityMatch = ISNULL(NextFlat.IsNationalityMatch, 0)
FROM FlatMaster
LEFT JOIN FlatOwnerNationality PrevFlat
ON PrevFlat.Floor = FlatMaster.Floor
AND PrevFlat.FlatNo = FlatMaster.FlatNo - 1
LEFT JOIN FlatOwnerNationality NextFlat
ON NextFlat.Floor = FlatMaster.Floor
AND NextFlat.FlatNo = FlatMaster.FlatNo + 1
), RankedFlats AS
( SELECT *,
RowNumber = ROW_NUMBER() OVER(ORDER BY PrevIsNationalityMatch DESC,
NextIsNationalityMatch DESC,
EmptyFloor DESC,
EmptyFlatsEitherSide DESC,
Floor,
FlatNo)
FROM Flats
WHERE IsOccupied = 'NO'
)
SELECT Floor,
FlatNo,
MatchedOn = CASE WHEN PrevIsNationalityMatch = 1 THEN 'First Flat after same nationality owner'
WHEN NextIsNationalityMatch = 1 THEN 'First Flat before same nationality owner'
WHEN EmptyFloor = 1 THEN 'No Nationality Match, placed on empty floor'
WHEN EmptyFlatsEitherSide = 1 THEN 'Next flat with empty flats either side'
ELSE 'First Available Flat'
END
FROM RankedFlats
WHERE RowNumber = 1;
<强> Brazil Example - Floor 1, Flat 4 强>
<强> England Example - Floor 1, Flat 2 强>
<强> Spain Example - Floor 2, Flat 1 强>
修改强>
DECLARE @NewOwnerNationality VARCHAR(20) = 'BRAZIL';
WITH FlatOwnerNationality AS
( SELECT FlatMaster.Floor,
FlatMaster.FlatNo,
FlatMaster.IsOccupied,
IsNationalityMatch = CASE WHEN OwnerMaster.OwnerNationality = @NewOwnerNationality THEN 1 ELSE 0 END
FROM FlatMaster
LEFT JOIN OwnerMaster
ON OwnerMaster.OwnerName = FlatMaster.OwnerName
), Flats AS
( SELECT FlatMaster.Floor,
FlatMaster.FlatNo,
FlatMaster.IsOccupied,
EmptyFlatsEitherSide = CASE WHEN PrevFlat.IsOccupied = 'NO' AND NextFlat.IsOccupied = 'NO' AND PrevFlat2.IsOccupied = 'NO' AND NextFlat2.IsOccupied = 'NO' THEN 1 ELSE 0 END,
EmptyFloor = CASE WHEN COUNT(CASE WHEN FlatMaster.IsOccupied = 'YES' THEN 1 END) OVER(PARTITION BY FlatMaster.Floor) = 0 THEN 1 ELSE 0 END,
PrevIsNationalityMatch = ISNULL(PrevFlat.IsNationalityMatch, 0),
NextIsNationalityMatch = ISNULL(NextFlat.IsNationalityMatch, 0)
FROM FlatMaster
LEFT JOIN FlatOwnerNationality PrevFlat
ON PrevFlat.Floor = FlatMaster.Floor
AND PrevFlat.FlatNo = FlatMaster.FlatNo - 1
LEFT JOIN FlatOwnerNationality NextFlat
ON NextFlat.Floor = FlatMaster.Floor
AND NextFlat.FlatNo = FlatMaster.FlatNo + 1
LEFT JOIN FlatMaster PrevFlat2
ON PrevFlat2.Floor = FlatMaster.Floor
AND PrevFlat2.FlatNo = FlatMaster.FlatNo - 2
LEFT JOIN FlatMaster NextFlat2
ON NextFlat2.Floor = FlatMaster.Floor
AND NextFlat2.FlatNo = FlatMaster.FlatNo + 2
), RankedFlats AS
( SELECT *,
RowNumber = ROW_NUMBER() OVER(ORDER BY PrevIsNationalityMatch DESC,
NextIsNationalityMatch DESC,
EmptyFloor DESC,
EmptyFlatsEitherSide DESC,
Floor,
FlatNo)
FROM Flats
WHERE IsOccupied = 'NO'
)
SELECT Floor,
FlatNo,
MatchedOn = CASE WHEN PrevIsNationalityMatch = 1 THEN 'First Flat after same nationality owner'
WHEN NextIsNationalityMatch = 1 THEN 'First Flat before same nationality owner'
WHEN EmptyFloor = 1 THEN 'No Nationality Match, placed on empty floor'
WHEN EmptyFlatsEitherSide = 1 THEN 'Next flat with empty flats either side'
ELSE 'First Available Flat'
END
FROM RankedFlats
WHERE RowNumber = 1;