根据动态比较查找匹配实体

内森·洛丁(Nathan Loding)

我不确定该主题是否真正有意义,但我不确定该如何措辞。设置如下:我有一个Item,其中有很多ItemLogic,每个都有一个Field每个Item都有25个ItemLogic实体。逻辑确定是否Item与表单中的给定输入匹配。例如,Field X has a value greater than AField Y has a value equal to B等每个25场。

在该应用程序的当前版本中,将查询所有相关实体并进行循环,返回所有ItemLogic所在的第一个匹配Item true它有点贵,但是代码简单,而且从来没有太多的项目可以看。到现在。

现在,该应用需要过滤3000个项目才能找到匹配项。上一个查询至少有两个联接,并且在我们的SQL实例上花费大约45秒。这太长了。

存储过程看起来很自然,但这很重要:每个项目的数据都是动态的,它以字符串值的形式出现,通常需要转换为其他类型(DateTime或int最常见)才能执行实际比较,某些逻辑将被忽略而不是进行比较。存储过程中有很多额外的开销,至少这是让我感到震惊的方法。

或者,我可以对数据进行分块,但这对于尝试匹配集合中的最后一个Item的穷人来说并不能节省太多。

有什么方法可以加快比赛速度?

模式和一些示例数据:

CREATE TABLE [dbo].[Items](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](255) NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

CREATE TABLE [dbo].[ItemLogic](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ItemId] [int] NOT NULL,
    [FieldId] [int] NOT NULL,
    [Value] [nvarchar](max) NULL,
    [Comparison] [int] NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

CREATE TABLE [dbo].[Fields](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Value] [nvarchar](max) NOT NULL,
    [Type] [int] NOT NULL,
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

INSERT INTO [dbo].[Fields] (Value, Type) VALUES ('abc', 0), ('def', 0), ('123', 1)

INSERT INTO [dbo].[Items] (Name) VALUES ('Item 1'), ('Item 2'), ('Item 3')

INSERT INTO [dbo].[ItemLogic] (ItemId, FieldId, Value, Comparison) VALUES (1, 1, 'xyz', 1), (1, 2, 'qrs', 1), (1, 3, '200', 0), (2, 1, 'abc', 1), (2, 2, 'xyz', 1), (2, 3, '123', 2), (3, 1, 'abc', 1), (3, 2, 'def', 1), (3, 2, '100', 0)

对于该Comparison字段,它是一个枚举匹配:0 =大于,1 =等于,2 =忽略。对于该Type字段,它是一个枚举匹配:0 =字符串,1 =整数。

上述匹配的预期结果应该Item 3是返回的。

耶稣洛佩兹

它将永远不会很快。但是,这是我能想到的最简单,最紧凑的解决方案:

SELECT * 
FROM 
    Items
WHERE 
    Id NOT IN (
        SELECT IL.ItemId
        FROM
            Fields F
            INNER JOIN ItemLogic IL
                ON F.Id = IL.FieldId
        WHERE
            NOT (
                IL.Comparison = 2 -- Ignore
                OR
                F.Type = 0 AND ( -- string types
                    IL.Comparison = 0 AND F.Value > IL.Value
                    OR 
                    IL.Comparison = 1 AND F.Value = IL.Value
                )
                OR
                F.Type = 1 AND ( -- integer types
                    IL.Comparison = 0 AND TRY_CAST(F.Value AS int) > TRY_CAST(IL.Value AS int)
                    OR 
                    IL.Comparison = 1 AND TRY_CAST(F.Value AS int) = TRY_CAST(IL.Value AS int)
                )
            )
        )

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章