2015-03-10 4 views
0

Мне нужно выбрать топ 1 наиболее актуальную скидку для данного FriendId. У меня есть следующие таблицы:SQL Select with Priority

DiscountTable - описывает различные типы скидок

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

Тогда у меня есть еще две таблицы (оба списка FriendIds)

Друзья

101 
102 
103 

O verwrites

101 
105 

я должен выбрать верхнюю 1 наиболее действительной скидку для данного FriendId. Таким образом, для вышеуказанных данных это будет выход проб

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) 

Таблицы перезаписей и друзей одинаковы. Они только держать список идентификаторов (одного столбца)

+0

Где бы '106' пришел с тех пор? Являются ли структуры 'Friends' и' Overwrites' фактически идентичными или просто для целей вашего образца? –

+0

С таким количеством очков, как вы здесь, вы должны знать, что вам нужно разместить больше информации, чем это. –

+0

Не можете ли вы просто выбрать топ 1 [Столбцы] из [таблиц] по ID? –

ответ

4

Наличие нескольких таблиц одинаковой структуры, как правило, плохая практика, одна таблица с ID и Type хватило бы, вы могли бы использовать его в 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 значения не возвращаются.

+0

это работает. Спасибо!. Если больше «Перезаписать» таблицы приходят, я думаю, я тоже мог бы СОЮЗ? – ShaneKm

+0

Вы, конечно, могли бы. –

+0

Этот запрос работает только для одного ID за раз. – shawnt00

0

Это даст вам все FriendIds и ассоциированную скидку самого высокого ранга. Это старый хак, который не требует использования нумерации сверху или ряда.

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 
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