2009-03-16 4 views
1

사용자/시스템과 관련된 몇 가지 매개 변수를 기반으로 사용자에게 보낼 SMS 메시지를 결정하는 조회 방법을 작성하려고합니다. 최후의 수단으로 사용될 기본 메시지가 있지만 다양한 매개 변수로 메시지를 무시하는 여러 가지 방법이 있습니다. 지금까지 내가 조회 조회를 위해 가지고있는 것이 있습니다 - 이것을하기위한 더 좋은 방법이 있습니까? 어쩌면 조회가 이것에 대한 올바른 접근법이 아닌가? 내가 가지고있는 쿼리 여기SQL에서 깔끔하게 채워지는 검색 테이블

ID Key CTID SPID DistID CampID Message 
    1 Help 1 NULL NULL NULL 'This is the default message' 
    2 Help 1 375 NULL NULL 'This is the SP375 message' 
    3 Help 1 377 NULL NULL 'This is the SP377 message' 
    4 Help 1 NULL 13  NULL 'This is the Dist13 message' 
    5 Help 1 375 13  NULL 'This is the SP375/Dist13 message' 
    6 Help 1 NULL 13  500 'This is the Dist13/Camp500 message' 
    7 Help 1 375 13  500 'This is the SP375/Dist13/Camp500 msg' 
    8 Help 1 NULL NULL 500 'This is the Camp500 help message' 

됩니다 :

select 
    --top 1 
    * 
from MessageLookup ml 
where ml.[Key] = @Key 
and ml.CampaignTypeID = @CampaignTypeID 
and 
(
    ml.ServiceProviderID = @ServiceProviderID or 
    ml.ServiceProviderID is null 
) 
and 
(
    ml.DistributorID = @DistributorID or 
    ml.DistributorID is null 
) 
and 
(
    ml.CampaignID = @CampaignID or 
    ml.CampaignID is null 
) 
order by 
    CampaignID desc, -- highest precedence lookup param 
    DistributorID desc, 
    ServiceProviderID desc -- lowest precedence lookup param 

답변

1

나는 최선의 방법이 무엇인지 모르겠지만, 여기에 몇 가지 대안 :

한 생각과 같이, 각각의 규칙과 패턴을 저장하는 것입니다 :

ID Key CTID Rule  Message 
1 Help 1 '[%:%:%]' 'This is the default message' 
2 Help 1 '[375:%:%]' 'This is the SP375 message' 
3 Help 1 '[377:%:%]' 'This is the SP377 message' 
4 Help 1 '[%:13:%]' 'This is the Dist13 message' 
5 Help 1 '[375:13:%]' 'This is the SP375/Dist13 message' 

그런 다음 모든 AND 대신 LIKE 테스트를 사용하십시오.

또 다른 생각은 OUTER JOINS를 사용하는 것입니다.

또는 서면에 의해 더 물건을 건조 (그냥 온 답을 재생) :

where ml.[Key] = @Key 
    and ml.CampaignTypeID = @CampaignTypeID 
    and IsNull(ml.ServiceProviderID = @ServiceProviderID,true) 
    and IsNull(ml.DistributorID  = @DistributorID, true) 
    and IsNull(ml.CampaignID  = @CampaignID,  true) 
+0

규칙 열이 재미 있습니다. 미래에 조회를 확장 할 수있는 방법을 제공 할 수도 있습니다. (어쨌든 ...) 답변 주셔서 감사합니다. –

2

여기

MessageLookup 
{ 
ID bigint PK       
Key varchar       
CampaignTypeID bigint FK,    
ServiceProviderID bigint FK nullable, -- optional override parameter 
DistributorID bigint FK nullable,  -- optional override parameter 
CampaignID bigint FK nullable,  -- optional override parameter 
Message varchar     
} 

테이블은 다음과 같은 형태가 될 것이다의 예입니다 : 여기

는 룩업 테이블 나는 그것이 유효한 접근법이라고 생각한다. 확장하기 쉽고, 의도는 분명하다. 그리고 다음을 수행하여 SQL을 정리할 수있다.

select 
    --top 1 
    * 
from MessageLookup ml 
where ml.[Key] = @Key 
and ml.CampaignTypeID = @CampaignTypeID 
and ml.ServiceProviderID = IsNull(@ServiceProviderID, ml.ServiceProviderID) 
and ml.DistributorID = IsNull(@DistributorID, ml.DistributorID) 
and ml.CampaignID = IsNull(@CampaignID, ml.CampaignID) 
.... 
1

당신이 일을 어떻게 이해하고 작품을 만든다. 모범 사례 후 "SELECT *"를 사용하지 않는 경우 - 선택할 열을 열거하십시오.

+0

이전에 들었습니다. 주로 성능에 대한 우려입니까, 아니면 미래의 변화로부터 자신을 보호하는 방법입니까, 아니면 다른 것입니까? –

+0

미래 지향적입니다 (가독성 - 다른 사람이 자신의 의도를 이해하는 것이 훨씬 쉽습니다). 누군가가 다시 만든 테이블에서 다른 순서로 열을 사용하는 등 재해가 발생하는 것을 보았습니다 ... – SquareCog

+0

관심없는 열이 수백 개있는 경우 성능 문제가 될 수 있습니다. 또한 어떤 열에 관심이 있는지 명확하지 않게 할 수 있습니다. –

0

나는 (MSGID, Key, CTID, Message)와 (MSGID, ID, IDTYPE)를 저장하는 또 다른 TB가 하나의 테이블 TA 인 다른 방식으로 데이터베이스를 설계 할 것이라고 생각합니다. CampID/DistId/DefaultId (IDTYPE로 표시)이며 PK는 (ID, IDTYPE, MSGID) 순서 여야합니다. IDTYPE에 우선 순위를 나타내는 숫자 값을 할당 할 수 있습니다. 기본값은 0이고 일치하는 ID는 0입니다. 모든 열은 NULL이 아닙니다.

문제가 잘 이해된다면 x, y, z 세 가지 값 (내 경우에는 암시 적 0)이 입력되고 가장 일치하는 메시지를 반환하고 싶습니다. 평등의 경우, IDTYPE의 경우.

select MSGID, count(*) as nbr_candidates, max(IDTYPE) as priority 
from TB 
where (ID = x and IDTYPE = ...) 
    or (ID = y and IDTYPE = ...) 
    or (ID = z and IDTYPE = ...) 
    or (ID = 0 and IDTYPE = 0) 
group by MSGID 
order by 2 desc, 3 desc 

는 첫 번째 행으로 "최고의 메시지"를 반환해야합니다, 당신은 추가 할 필요는

top 1 

다음 다른 테이블과 조인. 테이블 TB에는 숫자 ID 만 포함되어 있고 매우 컴팩트하므로 조인이 즉시 이루어지기 때문에 이는 한 테이블 솔루션보다 빠를 가능성이 높습니다.