質問

ユーザー/システムに関連付けられたいくつかのパラメーターに基づいて、ユーザーに送信するSMSメッセージを決定するためのルックアップメソッドを記述しようとしています。最後の手段として使用されるデフォルトのメッセージがありますが、さまざまなパラメーターによってメッセージをオーバーライドする方法は複数あります。ルックアップクエリについてこれまでに私が持っているものは次のとおりです-これを行うためのより良い方法はありますか?たぶん、ルックアップはこのための正しいアプローチではありませんか?

ルックアップテーブルは次のとおりです。

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                   
}

表は次のようになります。

   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
役に立ちましたか?

解決

最善の方法はわかりませんが、いくつかの選択肢があります:

次のように、各ルールにパターンを保存することを考えます:

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テストを使用します。

もう1つの考えは、外部結合を使用することです。

または(入ったばかりの答えを再生します)次のように書いてさらにDRYします:

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)

他のヒント

これは有効なアプローチであり、拡張が容易であり、意図は非常に明確であると思います。次のようにすると、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)
....

あなたがしていることは理にかなっており、動作します。 ベストプラクティスに従う場合は、<!> quot; SELECT * <!> quot;を使用しないでください。 -選択している列を列挙します。

別の方法でデータベースを設計すると思います。1つのテーブルTAは(MSGID、キー、CTID、メッセージ)で、もう1つのTBはIDがCampIDを表す場所(MSGID、ID、IDTYPE)になります/ DistId / DefaultId(IDTYPEで示されます)。PKはこの順序で(ID、IDTYPE、MSGID)になります。 IDTYPEには、優先順位を示す数値を割り当てることができます。デフォルトは0(および一致するIDは0)です。すべての列はNOT NULLです。

問題をよく理解している場合、入力はx、y、zの3つの値(この場合は暗黙的な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

<!> quot; best message <!> quot;を返す必要があります。最初の行として追加する必要があるのは

だけです
top 1

次に、他のテーブルと結合します。テーブルTBは数値IDのみを含み、非常にコンパクトであり、結合は即座に行われるため、これは1つのテーブルのソリューションよりも高速である可能性があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top