问题:我需要在表单上显示用户输入的字段,根据某些查找条件是动态的。
我目前的解决方案:我已经创建了一个SQL表,其中包含一些字段输入条件,它基于一个相对简单的匹配条件。匹配条件基本上是这样的: Lookup值以match Code开头,通过LEN比较找到最精确的匹配项。
select
f.[IS_REQUIRED]
, f.[MASK]
, f.[MAX_LENGTH]
, f.[MIN_LENGTH]
, f.[RESOURCE_KEY]
, f.[SEQUENCE]
from [dbo].[MY_RECORD] r with(nolock)
inner join [dbo].[ENTRY_FORMAT] f with(nolock)
on r.[LOOKUP_VALUE] like f.[MATCH_CODE]
-- Logic to filter by single, most-precise record match.
cross apply (
select f1.[SEQUENCE]
from [dbo].[ENTRY_FORMAT] f1 with(nolock)
where f.[SEQUENCE] = f1.[SEQUENCE]
and s.[MATCH_CODE] like f1.[MATCH_CODE]
group by f1.[SEQUENCE]
having len(f.[MATCH_CODE]) = max(len(f1.[MATCH_CODE]))
) tFilter
where r.[ID] = @RecordId当前的问题是,必须针对每个匹配计算每个调用的最精确匹配。此外,我目前只能在MATCH_CODE中支持%。(例如,'%'是所有LOOKUP_VALUE的默认设置,而输入'12%'将更精确地匹配LOOKUP_VALUE of '12345',而MATCH_CODE of '12345'显然应该是最精确的匹配。)但是,我想添加对[4-7]等通配符的支持。离开LEN,这肯定是错误的,因为'[4-7]'增加了很多长度,但是,例如,'12345'仍然是'123[4-7]'的理想匹配
我想要的更新是:向ENTRY_FORMAT添加一个MATCH_WEIGHT列,我可以通过insert/update时的触发器对其进行更新。对于我的初始实现,我只是在寻找一些可以逐个字符地通过MATCH_CODE,增加MATCH_WEIGHT,但在这样做时只将[..]视为单个字符的东西。是否有好的机制(UDF - SQL或CLR?光标?)通过迭代varchar字段的字符来以这种方式计算值?例如,每个非通配符增加两个MATCH_WEIGHT,可能在一个通配符上增加一个;细节有待进一步考虑和解决……
我们的目标是使用更像这样的查询:
select
f.[IS_REQUIRED]
, f.[MASK]
, f.[MAX_LENGTH]
, f.[MIN_LENGTH]
, f.[RESOURCE_KEY]
, f.[SEQUENCE]
from [dbo].[MY_RECORD] r with(nolock)
-- Logic to filter by single, most-precise record match.
cross apply (
select top 1
f1.[MATCH_CODE]
, f1.[SEQUENCE]
from [dbo].[ENTRY_FORMAT] f1 with(nolock)
where r.[LOOKUP_VALUE] like f1.[MATCH_CODE]
group by f1.[SEQUENCE]
order by f1.[MATCH_WEIGHT] desc
) tFilter
inner join [dbo].[ENTRY_FORMAT] f with(nolock)
on f.[MATCH_CODE] = tFilter.[MATCH_CODE]
and f.[SEQUENCE] = tFilter.[SEQUENCE]
where r.[ID] = @RecordId注意:我意识到这是一个相对脆弱的设置。ENTRY_FORMAT记录只由开发人员输入,他们知道这些限制,所以现在假设输入了有效数据,并且不会导致匹配冲突。
在一些帮助下,我已经提出了一个实现(答案如下),但我仍然不确定我的总体设计,所以欢迎更好的答案或任何批评。
发布于 2016-07-19 22:38:48
在Steve's answer on another question中,我使用了大部分代码来创建一个函数,以完成对匹配代码末尾的[..]通配符的支持。
CREATE FUNCTION CalculateMatchWeight
(
-- Add the parameters for the function here
@MatchCode varchar(100)
)
RETURNS smallint
AS
BEGIN
-- Declare the return variable here
DECLARE @Result smallint = 0;
-- Add the T-SQL statements to compute the return value here
DECLARE @Pos int = 1, @N0 int = ascii('0'), @N9 int = ascii('9'), @AA int = ascii('A'), @AZ int = ascii('Z'), @Wild int = ascii('%'), @Range int = ascii('[');
DECLARE @Asc int;
DECLARE @WorkingString varchar(100) = upper(@MatchCode)
WHILE @Pos <= LEN(@WorkingString)
BEGIN
SET @Asc = ascii(substring(@WorkingString, @Pos, 1));
If ((@Asc between @N0 and @N9) or (@Asc between @AA and @AZ))
SET @Result = @Result + 2;
ELSE
BEGIN
-- Check wildcard matching, update value according to match strength, and stop calculating further.
-- TODO: In the future we may wish to have match codes with wildcards not just at the end; try to figure out a mechanism to calculating that case.
IF (@Asc = @Range)
BEGIN
SET @Result = @Result + 2;
SET @Pos = 100;
END
IF (@Asc = @Wild)
BEGIN
SET @Result = @Result + 1;
SET @Pos = 100;
END
END
SET @Pos = @Pos + 1
END
-- Return the result of the function
RETURN @Result
END我已经检查过,这可以为我试图涵盖的当前情况生成所需的输出:
SELECT [dbo].[CalculateMatchWeight] ('12345'); -- Most precise (10)
SELECT [dbo].[CalculateMatchWeight] ('123[4-5]'); -- Middle (8)
SELECT [dbo].[CalculateMatchWeight] ('123%'); -- Least (7)现在,我可以在INSERT/UPDATE的触发器中调用此函数来更新MATCH_WEIGHT
CREATE TRIGGER TRG_ENTRY_FORMAT_CalcMatchWeight
ON ENTRY_FORMAT
AFTER INSERT,UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for trigger here
DECLARE @NewMatchWeight smallint = (select dbo.CalculateMatchWeight(inserted.MATCH_CODE) from inserted),
@CurrentMatchWeight smallint = (select inserted.MATCH_WEIGHT from inserted);
IF (@CurrentMatchWeight <> @NewMatchWeight)
BEGIN
UPDATE ENTRY_FORMAT
SET MATCH_WEIGHT = @NewMatchWeight
FROM inserted
WHERE ENTRY_FORMAT.[MATCH_CODE] = inserted.[MATCH_CODE]
AND ENTRY_FORMAT.[SEQUENCE] = inserted.[SEQUENCE]
END
ENDhttps://stackoverflow.com/questions/38442835
复制相似问题