如何编写SQL查询来检索与参数最接近的匹配项?

如何编写SQL查询来检索与参数最接近的匹配项?,sql,sql-server,sql-server-2008,tsql,Sql,Sql Server,Sql Server 2008,Tsql,假设您在SQL Server 2008 R2中有这样一个表(我们称之为RulesTable): Id | Type | SubType1 | SubType2 | Value 1 A A1 AA2 10 5 A A1 NULL 50 2 A NULL AA3 20 3 A

假设您在SQL Server 2008 R2中有这样一个表(我们称之为RulesTable):

Id    |   Type   | SubType1  | SubType2 | Value
  1        A         A1          AA2       10
  5        A         A1          NULL      50
  2        A        NULL         AA3       20
  3        A        NULL         NULL      30
  4      NULL       NULL         NULL      40
我将始终查询类型、子类型1和子类型2。如果缺少一个或多个,则假定它为空。查询应始终按照类型、子类型1、子类型2的顺序进行查询,并在搜索过程中缩小搜索范围,然后匹配最近的条目。下面是一些使用场景:

(1) 如果我查询类型='A',子类型1='B',子类型2='C',那么由于在表中找不到'B'或'C',它应该为它们使用null。因此,我将有效地查找Type='A',subpit1=NULL,subpit2=NULL,并且我应该以ID=3的值30结束

(2) 如果我查询类型='A',子类型1='A1',子类型2='C',那么子类型2应该=NULL,因为值不在表中,最接近的匹配是类型='A',子类型1='A1',子类型2=NULL,所以我应该以值=50结束

(3) 如果我查询类型='C',子类型1='C',子类型3='D',那么由于所有这些值都不在我的表中,它们都可以替换为null,因此我将有效地搜索类型=null,子类型1=null,子类型3=null,因此我应该得到值40或Id=4

因此,假设您有参数和结果表

MyId | Type |  SubType1 | SubType2 | Id  | Value
  1     A        B           C       ?      ?
  2     A       A1           C       ?      ?
  3     C        C           D       ?      ?

因此,我只是想了解如何编写一个函数来更新parameters和ResultsTable中的ID/值(使用Type、Subfit1、Subfit2作为参数),并使用上述逻辑提供RulesTable的数据。我想也许可以研究一下距离计算,但我正在寻找如何解决这个问题的想法…

这应该能满足您的需要,从最精确到最不精确的顺序:

SELECT *
FROM RulesTable
WHERE ISNULL([Type], @Param1) = @Param1
AND ISNULL(SubType1, @Param2) = @Param2
AND ISNULL(SubType2, @Param3) = @Param3
ORDER BY [Type] DESC,
SubType1 DESC,
SubType2 DESC

这将得到您想要的,从最精确到最不精确的顺序:

SELECT *
FROM RulesTable
WHERE ISNULL([Type], @Param1) = @Param1
AND ISNULL(SubType1, @Param2) = @Param2
AND ISNULL(SubType2, @Param3) = @Param3
ORDER BY [Type] DESC,
SubType1 DESC,
SubType2 DESC

这将得到您想要的,从最精确到最不精确的顺序:

SELECT *
FROM RulesTable
WHERE ISNULL([Type], @Param1) = @Param1
AND ISNULL(SubType1, @Param2) = @Param2
AND ISNULL(SubType2, @Param3) = @Param3
ORDER BY [Type] DESC,
SubType1 DESC,
SubType2 DESC

这将得到您想要的,从最精确到最不精确的顺序:

SELECT *
FROM RulesTable
WHERE ISNULL([Type], @Param1) = @Param1
AND ISNULL(SubType1, @Param2) = @Param2
AND ISNULL(SubType2, @Param3) = @Param3
ORDER BY [Type] DESC,
SubType1 DESC,
SubType2 DESC
下面是函数:

CREATE FUNCTION RuleTableFunction (@Type nvarchar(5), @SubType1 nvarchar(5), @SubType2 nvarchar(5))
RETURNS TABLE
AS
RETURN 
(
    SELECT 
        Id
        ,Value
    FROM 
        table_name 
    WHERE
        (Type = @Type OR Type IS NULL)
        and (SubType1 = @SubType1 OR SubType1 IS NULL)
        and (SubType2 = @SubType2 OR SubType2 IS NULL)
);
SELECT * FROM RuleTableFunction ('A','B','C');
要调用该函数,请执行以下操作:

CREATE FUNCTION RuleTableFunction (@Type nvarchar(5), @SubType1 nvarchar(5), @SubType2 nvarchar(5))
RETURNS TABLE
AS
RETURN 
(
    SELECT 
        Id
        ,Value
    FROM 
        table_name 
    WHERE
        (Type = @Type OR Type IS NULL)
        and (SubType1 = @SubType1 OR SubType1 IS NULL)
        and (SubType2 = @SubType2 OR SubType2 IS NULL)
);
SELECT * FROM RuleTableFunction ('A','B','C');
下面是函数:

CREATE FUNCTION RuleTableFunction (@Type nvarchar(5), @SubType1 nvarchar(5), @SubType2 nvarchar(5))
RETURNS TABLE
AS
RETURN 
(
    SELECT 
        Id
        ,Value
    FROM 
        table_name 
    WHERE
        (Type = @Type OR Type IS NULL)
        and (SubType1 = @SubType1 OR SubType1 IS NULL)
        and (SubType2 = @SubType2 OR SubType2 IS NULL)
);
SELECT * FROM RuleTableFunction ('A','B','C');
要调用该函数,请执行以下操作:

CREATE FUNCTION RuleTableFunction (@Type nvarchar(5), @SubType1 nvarchar(5), @SubType2 nvarchar(5))
RETURNS TABLE
AS
RETURN 
(
    SELECT 
        Id
        ,Value
    FROM 
        table_name 
    WHERE
        (Type = @Type OR Type IS NULL)
        and (SubType1 = @SubType1 OR SubType1 IS NULL)
        and (SubType2 = @SubType2 OR SubType2 IS NULL)
);
SELECT * FROM RuleTableFunction ('A','B','C');
下面是函数:

CREATE FUNCTION RuleTableFunction (@Type nvarchar(5), @SubType1 nvarchar(5), @SubType2 nvarchar(5))
RETURNS TABLE
AS
RETURN 
(
    SELECT 
        Id
        ,Value
    FROM 
        table_name 
    WHERE
        (Type = @Type OR Type IS NULL)
        and (SubType1 = @SubType1 OR SubType1 IS NULL)
        and (SubType2 = @SubType2 OR SubType2 IS NULL)
);
SELECT * FROM RuleTableFunction ('A','B','C');
要调用该函数,请执行以下操作:

CREATE FUNCTION RuleTableFunction (@Type nvarchar(5), @SubType1 nvarchar(5), @SubType2 nvarchar(5))
RETURNS TABLE
AS
RETURN 
(
    SELECT 
        Id
        ,Value
    FROM 
        table_name 
    WHERE
        (Type = @Type OR Type IS NULL)
        and (SubType1 = @SubType1 OR SubType1 IS NULL)
        and (SubType2 = @SubType2 OR SubType2 IS NULL)
);
SELECT * FROM RuleTableFunction ('A','B','C');
下面是函数:

CREATE FUNCTION RuleTableFunction (@Type nvarchar(5), @SubType1 nvarchar(5), @SubType2 nvarchar(5))
RETURNS TABLE
AS
RETURN 
(
    SELECT 
        Id
        ,Value
    FROM 
        table_name 
    WHERE
        (Type = @Type OR Type IS NULL)
        and (SubType1 = @SubType1 OR SubType1 IS NULL)
        and (SubType2 = @SubType2 OR SubType2 IS NULL)
);
SELECT * FROM RuleTableFunction ('A','B','C');
要调用该函数,请执行以下操作:

CREATE FUNCTION RuleTableFunction (@Type nvarchar(5), @SubType1 nvarchar(5), @SubType2 nvarchar(5))
RETURNS TABLE
AS
RETURN 
(
    SELECT 
        Id
        ,Value
    FROM 
        table_name 
    WHERE
        (Type = @Type OR Type IS NULL)
        and (SubType1 = @SubType1 OR SubType1 IS NULL)
        and (SubType2 = @SubType2 OR SubType2 IS NULL)
);
SELECT * FROM RuleTableFunction ('A','B','C');

所以我想我必须把这个改成“选择前1*”?否则,这不会返回所有可能可接受的集合,而不一定是最接近的集合吗?正确的,您可以在选择中包括“top 1”以仅获得最准确的记录。因此我想我必须将其更改为“select top 1*”?否则,这不会返回所有可能可接受的集合,而不一定是最接近的集合吗?正确的,您可以在选择中包括“top 1”以仅获得最准确的记录。因此我想我必须将其更改为“select top 1*”?否则,这不会返回所有可能可接受的集合,而不一定是最接近的集合吗?正确的,您可以在选择中包括“top 1”以仅获得最准确的记录。因此我想我必须将其更改为“select top 1*”?否则,这不会返回所有可能可接受的集合,而不一定是最接近的集合吗?正确,您可以在选择中包括“top 1”以仅获取最准确的记录。这不会返回所有可接受的匹配,而不一定是最接近的一个吗?我认为它同时返回这两个集合,它只返回符合以下条件的行“规则”。你应该测试它,看看它是否符合你的要求,以及“规则”是否得到尊重。对我来说,它是。这不一定会返回所有可接受的匹配项,而不一定是最接近的匹配项吗?我想它会同时返回两个匹配项,它只返回符合“规则”的行。你应该测试它,看看这是否符合你的要求,以及是否符合“规则”“我们受到尊重。对我来说是的。这不会返回所有可接受的匹配,而不一定是最接近的匹配吗?我认为它同时会返回这两个匹配,它只返回符合“规则”的行。您应该测试它,看看它是否符合您的要求,以及“规则”是否得到遵守。对我来说是的。这不会返回所有可接受的匹配,而不一定是最接近的匹配吗?我认为它同时会返回这两个匹配,它只返回符合“规则”的行。您应该测试它,看看它是否符合您的要求,以及“规则”是否得到遵守。对我来说是的。