1

我正在编写一个存储过程来获取基于下表的值。

在此处输入图像描述

我正在根据买家的国籍填充公寓。

存储过程必须根据以下规则返回下一个未占用的单位:

  • 如果有新条目,我需要建议与新人相同国籍的已占用公寓旁边的非占用公寓

  • 如果没有找到符合上述条件的情况,则在没有单位的楼层分配第一个单位

  • 如果没有找到符合上述条件的单位,则分配一个两侧至少有两个空单位的单位

  • 如果没有找到满足上述条件的匹配项,则根据排序顺序分配第一个空的单位

笔记:

  • 每个单位都由楼层和单位编号的组合来识别

  • 搜索时公寓和楼层的排序顺序应从 1 到 n

样本输入:姓名: RANDY 国籍: 巴西

样本输出:FLOOR:1 FLAT NO: 4(附图片)

4

1 回答 1

1

关键是为您的每个标准创建列,即如果隔壁的公寓业主具有相同的国籍,则为一列,如果楼层为空,则为一列。

然后,您可以采用所有标准并将它们放在一个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;
于 2013-05-04T12:53:05.677 回答