2017-11-08 12 views
1

私はarticlesdiscountsテーブルを持っています。 Articlesはファミリーとサブファミリーを持つことができます(そうでないか、空白にすることができます)。SQL Serverクエリを "CASE"する方法

記事:customer_id(順番を行います顧客)家族や亜科:私はに基づいて自分の割引との記事を取得する必要が

id | name | price | family | subfamily 
1 | art1 | 5  | F01 | A02 
2 | art2 | 4  | F01 | A03 
3 | art3 | 5.5 | F02 | 

割引

id | customer_id | family | subfamily | discount 
1 | ABC123  | F01 | A02  | 40% 
1 | ABC123  | F01 |   | 45% 
2 | CBD321  | F02 |   | 30% 

。記事は家族だけに基づいて割引(サブファミリーは空欄)または家族とサブファミリーに割引が適用される可能性がありますが、どちらも表の顧客IDに関連付けられている必要があります。 1つの記事が何にもマッチしない場合、彼の割引はその顧客にとってはnullになります。例えば、顧客ABC123'F01'/'A02'家族/サブファミリーにと'F01'/''家族割引があり、

SELECT a.*, d.discount 
FROM articles a 
LEFT JOIN discounts AS d ON a.family = d.family AND a.subfamily = d.subfamily 
AND d.customer_id = 'ABC123' 

しかし、あなたが見ることができるように:私はこのクエリを持っている割引と顧客の記事を取得する

まあ、。したがって、art1の割引を受けるのに問題はありませんが、art2はファミリーとサブファミリーに一致しません。正確な家族とサブファミリーとのマッチを検索して検索する方法はありますか?結果がない場合は、家族のみを検索しますか?したがって、お客様ABC123は、art1で40%の割引、商品に45%の割引がありますart2

ありがとうございました。

答えて

0

両方を使用して注文を使用しますが、最初にサブファミリーで注文し、次にlimit clausuleを使用して最初のマッチを取得します。

+0

良いアイデアをしていますが、必要*記事ごとにより良いマッチング割引*ので、あなたは単に結果を1つの行に制限することはできません。この作業をするには、 'SELECT'節でサブクエリーにするか、' OUTER APPLY'を使います。 –

0

これはいかがですか。どちらの両方が一致する必要がありますまたは唯一の家族が

SELECT a.*, d.discount 
FROM articles a 
LEFT JOIN discounts AS d ON (a.family = d.family AND a.subfamily = d.subfamily) OR (a.family = d.family) 
AND d.customer_id = 'ABC123' 
1

あなたはあなたが必要なものこの

select 
    a.*, 
    isnull(d.discount, d1.discount) as discount 
from articles a 
left join discounts as d 
    on a.family = d.family and a.subfamily = d.subfamily and d.customer_id = 'ABC123' 
left join discounts as d1 
    on a.family = d1.family and d1.subfamily = '' and d1.customer_id = 'ABC123' 
; 
+1

私はこの読みやすさのためにこのクエリが好きです。一致する家族割引と一致するサブファミリー割引を取得し、サブファミリー間の優先順位を家族のみの一致よりも優先させます。よくやった。私はこれをあなたのために修正し、 'd.customer_id = 'abc123''を2つのON句に移動しました。 –

0

ランキングされて試すことができます一致する必要があります。顧客ABC123は一般的に製品ファミリF01で40%、サブファミリーA02では40%しか得られません。したがって、F01/A02はより良い一致であり、したがってF01より優先されます。

select * 
from 
(
    select 
    a.*, 
    d.discount, 
    row_number() over (partition by a.id 
         order by case when a.subfamily = d.subfamily then 1 else 2 end 
        ) as rnk 
    from articles a 
    left join discounts d on a.family = d.family 
         and (a.subfamily = d.subfamily or d.subfamily = '') 
         and d.customer_id = 'ABC123' 
) ranked 
where rnk = 1; 

または私はよりエレガントな考慮ベストマッチングの割引、取得するためにOUTER APPLYを使用します:

あなたはランク付けを行うためにROW_NUMBERを使用することができ、一般的に

select a.*, d.discount 
from articles a 
outer apply 
(
    select top(1) * 
    from discounts d 
    where a.family = d.family 
    and (a.subfamily = d.subfamily or d.subfamily = '') 
    and d.customer_id = 'ABC123' 
    order by case when a.subfamily = d.subfamily then 1 else 2 end 
) d; 
関連する問題