2017-11-08 1 views
1

나는 articlesdiscounts 테이블이 있습니다. Articles에는 가족과 하위 가족이있을 수 있습니다 (또는 없거나 공백 일 수 있음)."사례"SQL Server 쿼리

기사 :

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% 

: 가족과 아과 customer_id (주문을 할 것입니다 고객). 기사는 그의 가족 (subfamily는 공백이다) 또는 그의 가족 및 subfamily에 근거를 두는 할인이있을 수 있었다 그러나 둘 다 테이블에 고객 id에 associed 필요가있다. 하나의 기사가 어떤 내용과도 일치하지 않으면 해당 고객의 할인이 null이됩니다.

음, 할인과 고객의 기사를 검색하기 위해 나는이 쿼리가 :

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' 

을하지만 당신이 볼 수있는, 예를 들어 고객 ABC123에 대한 'F01'/'A02' 가족/아과와 'F01'/'' 가족 할인이있다. 따라서 art1 할인 혜택을 받으려면 아무런 문제가 없지만 art2은 가족 및 하위 계급과 일치하지 않습니다. 정확한 가족 및 하위 가족과 일치하는 항목을 먼저 쿼리하고 검색 할 수있는 방법이 있습니까? 결과가 없으면 가족 만 검색 할 수 있습니까? 따라서 ABC123 고객은 art1에 40 % 할인을 적용하고 상품에 45 % 할인을 적용합니다. art2

감사합니다.

답변

0

둘 모두를 사용하여 순서를 사용하십시오.하지만 하위 패밀리를 먼저 주문한 다음 첫 번째 일치 항목을 얻으려면 한계 clausule을 사용하십시오.

+0

좋은 생각을하지만, 당신이 필요합니다 기사 당 * 더 잘 맞는 할인 *, 그래서 당신은 단순히 결과를 한 행으로 제한 할 수 없습니다. 이 작업을하기 위해서는'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

나는이 가독성에 대한 질문을 좋아한다. 일치하는 가족 할인 및 일치하는 하위 가족 할인을 얻고 가족 전용 경기보다 하위 가족 우선 순위를 우선합니다. 잘 했어. (단, 외부 조인 기준은 'ON' 절에 속합니다.이 문제를 해결하고'd.customer_id ='abc123''을 두 ON 절로 이동했습니다.) –

0

순위입니다 시도 할 수와 일치해야합니다. 고객 ABC123은 일반적으로 제품군 F01에서 40 %를 얻지 만 하위 제품군 A02에서는 40 %에 불과합니다. 따라서 F01/A02가 더 잘 일치하므로 F01보다 우선합니다.

당신은 순위 할 ROW_NUMBER을 사용할 수 있습니다 : 나는 더 우아한 고려 최고의 매칭 할인받을

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를 사용 : 일반적으로

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;