关键是为您的每个标准创建列,即如果隔壁的公寓业主具有相同的国籍,则为一列,如果楼层为空,则为一列。
然后,您可以采用所有标准并将它们放在一个ROW_NUMBER()
函数的 order by 中,以按照您定义的顺序获取公寓。以下查询中的关键部分是:
RowNumber = ROW_NUMBER() OVER(ORDER BY PrevIsNationalityMatch DESC,
NextIsNationalityMatch DESC,
EmptyFloor DESC,
EmptyFlatsEitherSide DESC,
Floor,
FlatNo)
四列 ( PrevIsNationalityMatch
, NextIsNationalityMatch
, EmptyFloor', 'EmptyFlatsEitherSide
) 都是位字段,因此如果存在前一个单位由同一国籍的人拥有的行,则该行将始终由 ROW_NUMBER 函数排名第一,否则它会查找下一个单位是否为由同一国籍的人拥有(我添加了这条规则,因为它看起来合乎逻辑,但可以通过从 order by 中删除它很容易地删除它),依此类推,直到它只剩下按楼层和平面编号排序。
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;
巴西示例 - 1 楼,4 楼
英格兰示例 - 1 楼,2 楼
西班牙示例 - 2 楼,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;