Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 查询以查找具有最多匹配列的记录,其中不匹配列有空格?_Sql_Sql Server 2008 R2 - Fatal编程技术网

Sql 查询以查找具有最多匹配列的记录,其中不匹配列有空格?

Sql 查询以查找具有最多匹配列的记录,其中不匹配列有空格?,sql,sql-server-2008-r2,Sql,Sql Server 2008 R2,问题 我正在尝试在SQL Server中编写一个存储过程,以查找最佳匹配记录。给定表中5列A、B、C、D和E对应的5个输入参数@A、@B、@C、@D和@E(全部为varchar50),我希望找到匹配列最多的记录。所选记录中不匹配的每列都应包含一个空格“” 例如,如果我有输入“Sony”、“PlayStation”、“Controller”、“Black”、“Districted”,并且我的表包含以下列: "Sony" "Playstation" "Unit" "Black" "Dama

问题

我正在尝试在SQL Server中编写一个存储过程,以查找最佳匹配记录。给定表中5列A、B、C、D和E对应的5个输入参数@A、@B、@C、@D和@E(全部为varchar50),我希望找到匹配列最多的记录。所选记录中不匹配的每列都应包含一个空格“”

例如,如果我有输入“Sony”、“PlayStation”、“Controller”、“Black”、“Districted”,并且我的表包含以下列:

"Sony"  "Playstation"  "Unit"   "Black"  "Damaged"
"Sony"  "Playstation"  " "      " "      " "
它应该返回第二行,因为有两个参数匹配,而对于不匹配的3个参数,则有空格。我不想返回第一行,因为即使4个参数匹配,中间的一个也不匹配,而且它不是一个空格。如果它是一个空格,第一排将是赢家

我的方法

有很多细节我无法透露,但我的基本方法(注意,我是一个SQL新手)是测试从最具体到最不具体的每个组合。因此,我的查询如下所示:

-- start with most specific
SELECT * FROM dbo.Items WHERE
   A = @A
   B = @B
   C = @C
   D = @D
   E = @E

-- if no matches, try next
IF @@ROWCOUNT = 0
SELECT * FROM dbo.Items WHERE
   A = @A
   B = @B
   C = SPACE(1)
   D = @D
   E = @E

... etc.

在我的例子中,我只需要真正测试16个配置,因为一些排列永远不会存在。即使如此,这似乎是一个非常低效的方式来实现我想要的。除此之外,它甚至不起作用。似乎与空间进行比较是有问题的,因为正在进行一些自动修剪。在任何情况下,我目前的方法似乎效率低下,而且不起作用——因此我向您寻求帮助。

我将对5次比较(A-E列之间)中的每一次进行评分,然后将分数相加

当可乐=任何一行的可乐时,得分为1

当可乐可乐和第二排可乐=''时,得0分

保留其余行不计分(colA分数为空)

最佳匹配项的得分最高,任何列中都没有空分

有道理吗

下面是一个用于设置列分数的示例update语句:

update table
set scoreAcol = scoreA, scoreAcol = scoreB, scoreCcol = scoreC, scoreDcol = scoreD, scoreEcol = scoreE
from
    (select
    case when cola = @a then 1 when cola= ' ' then 0 end as scoreA,
    case when colb = @b then 1 when colb= ' ' then 0 end as scoreb,
    case when colc = @c then 1 when colc= ' ' then 0 end as scorec,
    case when cold = @d then 1 when cold= ' ' then 0 end as scored,
    case when cole = @e then 1 when cole= ' ' then 0 end as scoree) s
from table
我假设您在再次评分之前将所有非空分数设置为空

要合计一行的分数,只需

update table set score = scoreAcol + scoreBcol + scoreCcol + scoreDcol + scoreEcol 

任何空值都将导致
得分
值为空。然后,要找到得分最高的匹配项,您可以按
得分
降序排序。

我将对5次比较(A-E列之间)中的每一次进行评分,然后将分数相加

当可乐=任何一行的可乐时,得分为1

当可乐可乐和第二排可乐=''时,得0分

保留其余行不计分(colA分数为空)

最佳匹配项的得分最高,任何列中都没有空分

有道理吗

下面是一个用于设置列分数的示例update语句:

update table
set scoreAcol = scoreA, scoreAcol = scoreB, scoreCcol = scoreC, scoreDcol = scoreD, scoreEcol = scoreE
from
    (select
    case when cola = @a then 1 when cola= ' ' then 0 end as scoreA,
    case when colb = @b then 1 when colb= ' ' then 0 end as scoreb,
    case when colc = @c then 1 when colc= ' ' then 0 end as scorec,
    case when cold = @d then 1 when cold= ' ' then 0 end as scored,
    case when cole = @e then 1 when cole= ' ' then 0 end as scoree) s
from table
我假设您在再次评分之前将所有非空分数设置为空

要合计一行的分数,只需

update table set score = scoreAcol + scoreBcol + scoreCcol + scoreDcol + scoreEcol 
任何空值都将导致
得分
值为空。然后,要找到得分最高的匹配项,您可以按
得分
降序进行排序。

类似的内容

-- Temp table to play with
SELECT 1 AS Id, 'Sony' AS A, 'Playstation' AS B, 'Unit' AS C, 'Black' AS D, 
    'Damaged' AS E
INTO #Items
UNION SELECT 2, 'Sony', 'Playstation', ' ', ' ', ' '

-- The query
DECLARE @a nvarchar(50), @b nvarchar(50), @c nvarchar(50), @d nvarchar(50), @e 

nvarchar(50)
SET @a = 'Sony'
SET @b = 'Playstation'
SET @c = 'Controller'
SET @d = 'Black'
SET @e = 'Damaged'

SELECT TOP 1 I.*
FROM (
    SELECT ID,
        CASE WHEN @a = a THEN 1 WHEN a = ' ' THEN 0 ELSE NULL END AS AResult,
        CASE WHEN @b = b THEN 1 WHEN b = ' ' THEN 0 ELSE NULL END AS BResult,
        CASE WHEN @c = c THEN 1 WHEN c = ' ' THEN 0 ELSE NULL END AS CResult,
        CASE WHEN @d = d THEN 1 WHEN d = ' ' THEN 0 ELSE NULL END AS DResult,
        CASE WHEN @e = e THEN 1 WHEN e = ' ' THEN 0 ELSE NULL END AS EResult
    FROM #Items
) IW
INNER JOIN #Items I ON I.ID = IW.ID
WHERE AResult IS NOT NULL AND BResult IS NOT NULL AND CResult IS NOT NULL 
    AND DResult IS NOT NULL AND EResult IS NOT NULL
ORDER BY AResult + BResult + CResult + DResult + EResult DESC
应返回此值的:

"Sony"  "Playstation"  " "      " "      " "
如果您将我玩过的临时表更改为:

SELECT 1 AS Id, 'Sony' AS A, 'Playstation' AS B, ' ' AS C, 'Black' AS D, 
    'Damaged' AS E
INTO #Items
UNION SELECT 2, 'Sony', 'Playstation', ' ', ' ', ' '
那你应该去

"Sony"  "Playstation"  " "   "Black"  "Damaged"
最后,如果您的临时表示例中有以下内容:

SELECT 1 AS Id, 'Sony' AS A, 'Playstation' AS B, 'Unit' AS C, 'Black' AS D, 
    'Damaged' AS E
INTO #Items
UNION SELECT 2, 'Sony', 'Playstation', 'Unit', ' ', ' '
不会返回任何内容,因为它们在第三列中都有“Unit”。

类似的内容

-- Temp table to play with
SELECT 1 AS Id, 'Sony' AS A, 'Playstation' AS B, 'Unit' AS C, 'Black' AS D, 
    'Damaged' AS E
INTO #Items
UNION SELECT 2, 'Sony', 'Playstation', ' ', ' ', ' '

-- The query
DECLARE @a nvarchar(50), @b nvarchar(50), @c nvarchar(50), @d nvarchar(50), @e 

nvarchar(50)
SET @a = 'Sony'
SET @b = 'Playstation'
SET @c = 'Controller'
SET @d = 'Black'
SET @e = 'Damaged'

SELECT TOP 1 I.*
FROM (
    SELECT ID,
        CASE WHEN @a = a THEN 1 WHEN a = ' ' THEN 0 ELSE NULL END AS AResult,
        CASE WHEN @b = b THEN 1 WHEN b = ' ' THEN 0 ELSE NULL END AS BResult,
        CASE WHEN @c = c THEN 1 WHEN c = ' ' THEN 0 ELSE NULL END AS CResult,
        CASE WHEN @d = d THEN 1 WHEN d = ' ' THEN 0 ELSE NULL END AS DResult,
        CASE WHEN @e = e THEN 1 WHEN e = ' ' THEN 0 ELSE NULL END AS EResult
    FROM #Items
) IW
INNER JOIN #Items I ON I.ID = IW.ID
WHERE AResult IS NOT NULL AND BResult IS NOT NULL AND CResult IS NOT NULL 
    AND DResult IS NOT NULL AND EResult IS NOT NULL
ORDER BY AResult + BResult + CResult + DResult + EResult DESC
应返回此值的:

"Sony"  "Playstation"  " "      " "      " "
如果您将我玩过的临时表更改为:

SELECT 1 AS Id, 'Sony' AS A, 'Playstation' AS B, ' ' AS C, 'Black' AS D, 
    'Damaged' AS E
INTO #Items
UNION SELECT 2, 'Sony', 'Playstation', ' ', ' ', ' '
那你应该去

"Sony"  "Playstation"  " "   "Black"  "Damaged"
最后,如果您的临时表示例中有以下内容:

SELECT 1 AS Id, 'Sony' AS A, 'Playstation' AS B, 'Unit' AS C, 'Black' AS D, 
    'Damaged' AS E
INTO #Items
UNION SELECT 2, 'Sony', 'Playstation', 'Unit', ' ', ' '

不会返回任何内容,因为它们在第三列中都有“Unit”。

在SQl Server中,您可以使用CTE和Nullif之类的内容(未测试)

);带计数(id、A计数、B计数、C计数、D计数、E计数) 作为 (选择id、sum(当A=@A或null时,如果(A'')为null,则选择1,否则选择0结束)作为帐户 ,sum(当b=@b或null时,如果(b,,)为null,则为1,否则为0结束)作为bCount ,sum(当c=@c或null时,如果(c,,)为null,则为1,否则为0结束)作为帐户 ,sum(当d=@d或null时,如果(d,,)为null,则为1,否则为0结束)作为dCount ,sum(当e=@e或null时,如果(e,,)为null,则为1,否则为0结束)作为eCount 来自dbo.items)

,总计(id,Totalcount) 作为 (从计数中选择id、最大值(A计数+B计数+C计数+D计数+E计数)作为totalCount 其中A账户0和B账户0和C账户0和D账户0和E账户0 按id分组)

选择i.id、i.a、i.b、i.c、i.d、i.e 来自dbo.items i 在i.id=t.id上连接总计t
当然,参数的实际定义是什么。

在SQl Server中,您可以使用CTE和NULL,如果是这样的(未测试)

);带计数(id、A计数、B计数、C计数、D计数、E计数) 作为 (选择id、sum(当A=@A或null时,如果(A'')为null,则选择1,否则选择0结束)作为帐户 ,sum(当b=@b或null时,如果(b,,)为null,则为1,否则为0结束)作为bCount ,sum(当c=@c或null时,如果(c,,)为null,则为1,否则为0结束)作为帐户 ,sum(当d=@d或null时,如果(d,,)为null,则为1,否则为0结束)作为dCount ,sum(当e=@e或null时,如果(e,,)为null,则为1,否则为0结束)作为eCount 来自dbo.items)

,总计(id,Totalcount) 作为 (从计数中选择id、最大值(A计数+B计数+C计数+D计数+E计数)作为totalCount 其中A账户0和B账户0和C账户0和D账户0和E账户0 按id分组)

选择i.id、i.a、i.b、i.c、i.d、i.e 来自dbo.items i 在i.id=t.id上连接总计t
当然,参数的实际定义是什么。

所以基本上是以最少的错误匹配数排序?@LittleBobbyTables,我想返回一条记录,或者根本不返回。如果一个记录被返回,除了“.顺便说一句,Dalal,我认为你可能有不止一个匹配,例如,一行中有一个colB中的匹配项和一个colC中的空格,另一行中有一个colB中的空格和一个colC中的匹配项