SQL中填充稀疏的查找表
我正在尝试编写一个查找方法,用于根据与用户/系统相关的几个参数确定要发送给用户的SMS消息。我们将使用默认消息作为最后手段,但是有多种方法可以通过各种参数覆盖消息。以下是我到目前为止对查找查询的了解——有没有更好的方法?也许查找不是解决这个问题的正确方法 以下是查找表:SQL中填充稀疏的查找表,sql,lookup,Sql,Lookup,我正在尝试编写一个查找方法,用于根据与用户/系统相关的几个参数确定要发送给用户的SMS消息。我们将使用默认消息作为最后手段,但是有多种方法可以通过各种参数覆盖消息。以下是我到目前为止对查找查询的了解——有没有更好的方法?也许查找不是解决这个问题的正确方法 以下是查找表: MessageLookup { ID bigint PK Key varchar CampaignTypeID bigin
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
我认为这是一种有效的方法,易于扩展,目的非常明确,您可以通过执行以下操作来整理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)
....
我认为这是一种有效的方法,易于扩展,目的非常明确,您可以通过执行以下操作来整理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)
....
我不确定最好的方法是什么,但这里有一些替代方法: 一种想法是用每个规则存储一个模式,如下所示:
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
另一个想法是使用外部联接
或者(玩弄刚刚得到的答案)写下以下内容,让事情更加干涸:
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)
我不确定最好的方法是什么,但这里有一些替代方法: 一种想法是用每个规则存储一个模式,如下所示:
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
另一个想法是使用外部联接
或者(玩弄刚刚得到的答案)写下以下内容,让事情更加干涸:
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)
你所做的是有意义的,并且有效的。
如果您在追求最佳实践--不要使用“选择*”--请列举您正在选择的列。您所做的一切都是有意义的,并且是有效的。
如果您追求最佳实践--不要使用“SELECT*”--列举您正在选择的列。我想我应该以不同的方式设计数据库,一个表TA是(MSGID、Key、CTID、Message),另一个表TB是存储(MSGID、ID、IDTYPE),其中ID表示CampID/DistId/DefaultId(由IDTYPE表示),其主键应按此顺序为(ID、IDTYPE、MSGID)。您可以为IDTYPE指定一个指示优先级的数值,默认值为0(匹配的ID为0)。所有列都不是空的 如果我很理解您的问题,您的输入由三个值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
应该返回“best message”作为第一行,您只需要添加一个
top 1
然后加入另一个表。这可能比单表解决方案快,因为表TB只包含数字ID,而且非常紧凑,连接将是即时的。我想我应该以不同的方式设计数据库,一个表TA是(MSGID、Key、CTID、Message),另一个表TB是存储(MSGID、ID、IDTYPE)其中ID表示CampID/DistId/DefaultId(由IDTYPE表示),其主键按此顺序应为(ID,IDTYPE,MSGID)。您可以为IDTYPE指定一个指示优先级的数值,默认值为0(匹配的ID为0)。所有列都不是空的 如果我很理解您的问题,您的输入由三个值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
应该返回“best message”作为第一行,您只需要添加一个
top 1
然后加入另一个表。这可能比单表解决方案快,因为表TB只包含数字ID,而且非常紧凑,并且连接将是即时的。规则列很有趣。它可能提供了将来扩展查找的方法(不知何故…)感谢您的回答规则栏很有趣。它可能会在将来提供扩展查找的方法(不知何故…)谢谢你的回答,我以前听说过。它主要是一种性能问题,还是一种保护自己不受未来变化影响的方法,还是其他什么?它是未来的证明(加上可读性——其他人更容易理解您的意图)。我见过一些灾难发生的原因,比如有人在重新创建的表上使用*之类的东西,列的顺序不同……如果您有数百个不感兴趣的列,这可能会影响性能。这也会让你不太清楚你感兴趣的专栏是什么。我假设您使用*是因为您实际上对所有列都感兴趣。在一般情况下,你可以通过明确列出你想要的东西来节省很多钱。我以前听说过。它主要是一种性能问题,还是一种保护自己不受未来变化影响的方法,还是其他什么?它是未来的证明(加上可读性——其他人更容易理解您的意图)。我见过一些灾难发生的原因,比如有人在重新创建的表上使用*之类的东西,列的顺序不同……如果您有数百个不感兴趣的列,这可能会影响性能。这也会让你不太清楚你感兴趣的专栏是什么。我假设您使用*是因为您实际上对所有列都感兴趣。在一般情况下,通过明确列出所需内容,您可以获得显著的节约。