我正在一个停车场工作,障碍物上有摄像头,当这些摄像头看到车牌时,该牌照将作为一个动作在数据库中注册。
如果这个许可证有加入许可,停车场就会开放,但摄像头并不完美地获得许可证,也许有时我会得到一些字符不同的许可证。
我的意思是,例如,如果许可证是 7631 BHC,我可能会得到一个错误的值,可能是 1931 5HD。
我想知道的是,SQL 中是否有任何方法可以在选择中执行 WHERE 以查看许可证是否具有权限,以获取可能是相机返回的许可证。
例如,在我显示的情况下,有 3 个字符与可能值 (3,1,H) 匹配。
因此,当我在 C# 后台工作时,我的角色有这 3 个巧合,我会说,如果有超过 2 个巧合,障碍就会打开。
您知道有什么方法可以返回可能的许可证吗?
我尝试了函数 Difference() 但这个选项对我不起作用,因为总是返回 4 (这意味着值非常相似),但事实并非如此,因为许可证的值是 (9999 HHH,1234 ZZZ),按票价除了字符串的结构之外,它们并不相似。
给定一个用户定义的函数:
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
如果您的输入数据和源数据始终匹配模式
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
对我来说,搜索错误扫描的车牌最大的问题是车牌相似度的问题,例如:
"B" can be "8" "0" can be an "O" or even a "D"; "I" can be "1" ; "S"="5" ; "Z"="2"..... and so on.
当照片摇晃时,这种情况经常发生。