جدول بحث قليلة الكثافة السكانية في SQL
سؤال
وأنا أحاول أن أكتب طريقة البحث لتحديد رسالة 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'
ومن ثم استخدام اختبار LIKE بدل كل يستخدم المعامل.
وفكرة أخرى تتمثل في استخدام الخارجي تنضم.
وأو (اللعب خارج الجواب الذي جاء فقط في) لتجف الامور مزيدا من الكتابة:
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
--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)
....
ما تقومون به من المنطقي، ويعمل. إذا كنت بعد أفضل الممارسات - لا تستخدم "SELECT *" - تعداد الأعمدة التي تقوم بتحديد
وأنا أعتقد أن تصميم قاعدة البيانات بطريقة مختلفة، مع طاولة واحدة TA التي من شأنها أن تكون (MSGID، مفتاح، CTID، رسالة) والسل واحد آخر من شأنه أن تخزين (MSGID، ID، IDTYPE) حيث ID سيمثل CampID / DistId / DefaultId (المشار إليها IDTYPE)، وPK من الذي ينبغي أن يكون (ID، IDTYPE، MSGID) في هذا النظام. يمكنك أن تخصص IDTYPE قيمة رقمية تشير إلى الأولوية، مع 0 لصالح الافتراضي (وID مطابقة 0). جميع الأعمدة NOT 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 يحتوي فقط على معرفات رقمية وسيكون مضغوط جدا، والانضمام سيكون حظة.