我正在尝试编写一种查找方法,用于根据与用户/系统关联的一些参数确定要发送给用户的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
答案 0 :(得分:2)
我认为这是一种有效的方法,易于扩展,意图非常明确,您可以通过执行以下操作来整理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 :(得分: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'
然后使用LIKE测试代替所有AND。
另一种想法是使用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)
答案 2 :(得分:1)
你在做什么是有道理的,也是有效的。 如果您遵循最佳实践 - 请勿使用“SELECT *” - 枚举您选择的列。
答案 3 :(得分:0)
我想我会以不同的方式设计数据库,一个表TA将是(MSGID,Key,CTID,Message),另一个TB将存储(MSGID,ID,IDTYPE),其中ID表示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并且非常紧凑,并且连接将是即时的。