SQL选择优先级

时间:2015-03-10 19:05:27

标签: sql sql-server select

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

DiscountTable - 介绍不同的折扣类型

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

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

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)

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

3 个答案:

答案 0 :(得分:4)

具有相同结构的多个表通常是不好的做法,只有IDType的单个表就足够了,然后您可以在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值不会返回。

答案 1 :(得分:0)

这将为您提供最高级别的所有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

答案 2 :(得分:0)

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