带优先级的SQL选择

带优先级的SQL选择,sql,sql-server,select,Sql,Sql Server,Select,我需要为给定的FriendId选择前1个最有效的折扣。 我有以下表格: 折扣表-描述不同的折扣类型 DiscountId, Percent, Type, Rank 1 , 20 , Friend, 2 2 , 10 , Overwrite, 1 然后我有另外两个表(都列出了FriendID) 朋友 101 102 103 101 105 覆盖 101 102 103 101 105 我必须为给定的FriendI

我需要为给定的FriendId选择前1个最有效的折扣。 我有以下表格:

折扣表-描述不同的折扣类型

DiscountId, Percent, Type,        Rank
1         , 20     , Friend,      2
2         , 10     , Overwrite,   1
然后我有另外两个表(都列出了FriendID)

朋友

101
102
103
101
105
覆盖

101
102
103
101
105
我必须为给定的FriendId选择前1个最有效的折扣。因此,对于上述数据,这将是样本输出

Id = 101 => gets "Overwrite" discount (higher rank)
Id = 102 => gets "Friend" discount (only in friends table)
Id = 103 => gets "Friend" discount (only in friends table)
Id = 105 => gets "Overwrite" discount
Id = 106 => gets NO discount as it does not exist in neither Friend and overwrite tables


INPUT => SINGLE friendId (int). 
OUTPUT => Single DISCOUNT Record (DiscountId, Percent, Type)

覆盖和朋友表是相同的。它们只保存ID列表(单列)

具有多个相同结构的表通常是不好的做法,一个带有
ID
类型的表就足够了,然后您可以在
加入
折扣表中使用它:

;WITH cte AS (SELECT ID,[Type] = 'Friend' 
              FROM  Friends
              UNION  ALL
              SELECT ID,[Type] = 'Overwrite' 
              FROM  Overwrites
              )
SELECT TOP 1 a.[Type]
FROM cte a
JOIN DiscountTable DT
  ON a.[Type] = DT.[Type]
WHERE ID = '105'
ORDER BY [Rank]

注意,不存在的
ID
值将不会返回。

具有多个相同结构的表通常是不好的做法,一个具有
ID
类型的表就足够了,然后您可以在
加入
折扣表中使用它:

;WITH cte AS (SELECT ID,[Type] = 'Friend' 
              FROM  Friends
              UNION  ALL
              SELECT ID,[Type] = 'Overwrite' 
              FROM  Overwrites
              )
SELECT TOP 1 a.[Type]
FROM cte a
JOIN DiscountTable DT
  ON a.[Type] = DT.[Type]
WHERE ID = '105'
ORDER BY [Rank]

注意,不存在的
ID
值将不会返回。

这将为您获得所有FriendID和最高级别的关联折扣。这是一个较老的黑客,不需要使用顶部或行编号

select
    elig.FriendId,
    min(Rank * 10000 + DiscountId) % 10000 as DiscountId
    min(Rank * 10000 + Percent) % 10000 as Percent,
from 
    DiscountTable as dt
    inner join (
        select FriendId, 'Friend' as Type from Friends union all
        select FriendId, 'Overwrite' from Overwrites
    ) as elig /* for eligible? */
        on elig.Type = dt.Type
group by
    elig.FriendId

这将为您获得所有最高级别的FriendID和同事折扣。这是一个较老的黑客,不需要使用顶部或行编号

select
    elig.FriendId,
    min(Rank * 10000 + DiscountId) % 10000 as DiscountId
    min(Rank * 10000 + Percent) % 10000 as Percent,
from 
    DiscountTable as dt
    inner join (
        select FriendId, 'Friend' as Type from Friends union all
        select FriendId, 'Overwrite' from Overwrites
    ) as elig /* for eligible? */
        on elig.Type = dt.Type
group by
    elig.FriendId

那么,
106
将从何而来?
Friends
Overwrites
的结构实际上是相同的吗?或者仅仅是为了您的示例?这里有这么多的要点,您应该知道您需要发布更多的信息。您不能简单地从[表]中选择前1个[列]按ID订购?是朋友还是覆盖仅有的两个潜在折扣?或者以后还会添加更多?目前只使用这两个表。那么
106
将从何而来?
Friends
Overwrites
的结构实际上是相同的吗?或者仅仅是为了您的示例?这里有这么多的要点,您应该知道您需要发布更多的信息。您不能简单地从[表]中选择前1个[列]按ID订购?是朋友还是覆盖仅有的两个潜在折扣?或者以后还会添加更多?目前只使用这两个表。这很有效。非常感谢。“如果有更多的“覆盖”表出现,我想我也可以合并它?”shawnt00同意,这就是我理解OP要寻找的。如果需要不同,我会使用
行号()
和另一个cte来提取所有ID。这很有效。非常感谢。“如果有更多的“覆盖”表出现,我想我也可以合并它?”shawnt00同意,这就是我理解OP要寻找的。如果需要不同,我会使用
行号()
和另一个cte来提取所有ID。