如何执行Where并按相似值查找

问题描述 投票:0回答:3

我正在一个停车场工作,障碍物上有摄像头,当这些摄像头看到车牌时,该牌照将作为一个动作在数据库中注册。

如果这个许可证有加入许可,停车场就会开放,但摄像头并不完美地获得许可证,也许有时我会得到一些字符不同的许可证。

我的意思是,例如,如果许可证是 7631 BHC,我可能会得到一个错误的值,可能是 1931 5HD。

我想知道的是,SQL 中是否有任何方法可以在选择中执行 WHERE 以查看许可证是否具有权限,以获取可能是相机返回的许可证。

例如,在我显示的情况下,有 3 个字符与可能值 (3,1,H) 匹配。

因此,当我在 C# 后台工作时,我的角色有这 3 个巧合,我会说,如果有超过 2 个巧合,障碍就会打开。

您知道有什么方法可以返回可能的许可证吗?

我尝试了函数 Difference() 但这个选项对我不起作用,因为总是返回 4 (这意味着值非常相似),但事实并非如此,因为许可证的值是 (9999 HHH,1234 ZZZ),按票价除了字符串的结构之外,它们并不相似。

sql .net sql-server select where-clause
3个回答
0
投票

给定一个用户定义的函数:

CREATE FUNCTION dbo.CountMatches(@value NVARCHAR(100), @match NVARCHAR(100))
RETURNS INT AS
BEGIN
   DECLARE @i INT = 1;
   DECLARE @count INT = 0
   WHILE(@i < LEN(@match) AND @i<LEN(@value))
   BEGIN
      IF(SUBSTRING(@value,@i,1) = SUBSTRING(@match,@i,1))
      BEGIN
         SET @count = @count+1
      END
      SET @i = @i+1
   END
   RETURN @count
END

您可以将其直接插入到您的 where 子句中:

declare @camera nvarchar(100) = '19315HD'
SELECT plate
FROM Plates
WHERE dbo.CountMatches(plate,@camera) >= 3

或者,您希望结果和 where 子句中的匹配计数使用 CTE 来节省调用该方法两次

declare @camera nvarchar(100) = '19315HD'
;with data
as
(
    SELECT plate, dbo.CountMatches(plate, @camera) AS matchCount
    FROM Plates
)
select plate,matchCount
from data
where matchCount>=3

现场示例:https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=e55ae3788616ce14c3888db19d4aa865


0
投票

如果您的输入数据和源数据始终匹配模式

XXXX XXX
(8 个字符,第 5 个字符是空格),那么您可以只需对此进行硬编码...

样本数据

declare @input nvarchar(8) = '1931 5HD';

declare @plates table
(
    plate nvarchar(8)
)
insert into @plates (plate) values
('1235 ZZZ'), -- 0 matches
('7631 BHC'), -- 3 matches
('1931 5HC'); -- 6 matches

解决方案

-- version 1
select  p.plate
from @plates p
where   case when substring(p.plate, 1, 1) = substring(@input, 1, 1) then 1 else 0 end
      + case when substring(p.plate, 2, 1) = substring(@input, 2, 1) then 1 else 0 end
      + case when substring(p.plate, 3, 1) = substring(@input, 3, 1) then 1 else 0 end
      + case when substring(p.plate, 4, 1) = substring(@input, 4, 1) then 1 else 0 end
      + case when substring(p.plate, 6, 1) = substring(@input, 6, 1) then 1 else 0 end
      + case when substring(p.plate, 7, 1) = substring(@input, 7, 1) then 1 else 0 end
      + case when substring(p.plate, 8, 1) = substring(@input, 8, 1) then 1 else 0 end > 2;

如果你想要匹配字符的数量,那么你可以在字段列表中复制where子句的计算。这样,您甚至可以在按匹配字符数降序排序时仅选择

top 1
结果,从而为您提供最准确的车牌匹配。

-- version 2
select  top 1
        p.plate,
        case when substring(p.plate, 1, 1) = substring(@input, 1, 1) then 1 else 0 end
      + case when substring(p.plate, 2, 1) = substring(@input, 2, 1) then 1 else 0 end
      + case when substring(p.plate, 3, 1) = substring(@input, 3, 1) then 1 else 0 end
      + case when substring(p.plate, 4, 1) = substring(@input, 4, 1) then 1 else 0 end
      + case when substring(p.plate, 6, 1) = substring(@input, 6, 1) then 1 else 0 end
      + case when substring(p.plate, 7, 1) = substring(@input, 7, 1) then 1 else 0 end
      + case when substring(p.plate, 8, 1) = substring(@input, 8, 1) then 1 else 0 end as MatchCount
from @plates p
where   case when substring(p.plate, 1, 1) = substring(@input, 1, 1) then 1 else 0 end
      + case when substring(p.plate, 2, 1) = substring(@input, 2, 1) then 1 else 0 end
      + case when substring(p.plate, 3, 1) = substring(@input, 3, 1) then 1 else 0 end
      + case when substring(p.plate, 4, 1) = substring(@input, 4, 1) then 1 else 0 end
      + case when substring(p.plate, 6, 1) = substring(@input, 6, 1) then 1 else 0 end
      + case when substring(p.plate, 7, 1) = substring(@input, 7, 1) then 1 else 0 end
      + case when substring(p.plate, 8, 1) = substring(@input, 8, 1) then 1 else 0 end > 2
order by MatchCount desc;

另一个版本使用公共表表达式(

cte
)来避免一些重复的代码。受到Jamiec 的评论的启发。

-- version 3
with cte as
(
    select  p.plate,
            case when substring(p.plate, 1, 1) = substring(@input, 1, 1) then 1 else 0 end
          + case when substring(p.plate, 2, 1) = substring(@input, 2, 1) then 1 else 0 end
          + case when substring(p.plate, 3, 1) = substring(@input, 3, 1) then 1 else 0 end
          + case when substring(p.plate, 4, 1) = substring(@input, 4, 1) then 1 else 0 end
          + case when substring(p.plate, 6, 1) = substring(@input, 6, 1) then 1 else 0 end
          + case when substring(p.plate, 7, 1) = substring(@input, 7, 1) then 1 else 0 end
          + case when substring(p.plate, 8, 1) = substring(@input, 8, 1) then 1 else 0 end as MatchCount
    from @plates p
)
select top 1 plate, MatchCount
from cte
where MatchCount > 2
order by MatchCount desc;

结果

-- version 1
plate
--------
7631 BHC
1931 5HC

-- version 2 & 3
plate    MatchCount
-------- -----------
1931 5HC 6

0
投票

对我来说,搜索错误扫描的车牌最大的问题是车牌相似度的问题,例如:

"B" can be "8" "0" can be an "O" or even a "D"; "I" can be "1" ;  "S"="5" ; "Z"="2"..... and so on.

当照片摇晃时,这种情况经常发生。

© www.soinside.com 2019 - 2024. All rights reserved.