SQL Select 优先

SQL Select with Priority

我需要 select 给定 FriendId 的前 1 个最有效的折扣。 我有下表:

DiscountTable - 描述不同的折扣类型

DiscountId, Percent, Type,        Rank
1         , 20     , Friend,      2
2         , 10     , Overwrite,   1

然后我有另外两个表(都列出 FriendIds)

好友

101
102
103

覆盖

101
105

我必须 select 给定 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)

Overwrites 和 Friend 表是一样的。它们只包含 ID 列表(单列)

具有多个相同结构的 table 通常是不好的做法,一个带有 IDType 的 table 就足够了,然后您可以在JOIN 到您的 DiscountTable:

;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 值不会 return。

这会让你得到所有的FriendIds和最高等级的伙伴折扣。这是一个较旧的 hack,不需要使用顶部或行编号。

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
create table discounts (id int, percent1 int, type1 varchar(12), rank1 int)

insert into discounts
 values (1         , 20     , 'Friend',      2),

(2         , 10     , 'Overwrite',   1)


create table friends (friendid int)

insert into friends values (101),(102), (103)

create table overwrites (overwriteid int) 
insert into overwrites values (101),(105)

 select ids, isnull(percent1,0) as discount from (
select  case when   friendid IS null and overwriteid is null then 'no discount'
 when friendid is null and overwriteid is not null then 'overwrite'

      when friendid is not null and overwriteid is null then 'friend' 

      when friendid is not null and overwriteid is not  null then (select top 1 TYPE1 from discounts order by rank1 desc)
      else '' end category
      ,ids
  from tcase left outer join friends 
on tcase.ids = friends.friendid
left join overwrites
on tcase.ids = overwrites.overwriteid
 ) category1 left join discounts
 on category1.category=discounts.type1