Php 改进的分步SQL查询,无需许多IF/ELSE块
考虑一个包含以下行的示例表:Php 改进的分步SQL查询,无需许多IF/ELSE块,php,sql,azure,azure-sql-database,Php,Sql,Azure,Azure Sql Database,考虑一个包含以下行的示例表: +----+----------+-------+ | id | postcode | value | +----+----------+-------+ | 1 | A1A3A3 | one | | 2 | A1A3A4 | two | | 3 | A1A3B | three | | 4 | A1A3C | four | | 5 | A1A3D | five | | 6 | A1A3 | six | |
+----+----------+-------+
| id | postcode | value |
+----+----------+-------+
| 1 | A1A3A3 | one |
| 2 | A1A3A4 | two |
| 3 | A1A3B | three |
| 4 | A1A3C | four |
| 5 | A1A3D | five |
| 6 | A1A3 | six |
| 7 | A1A | seven |
| 8 | A1 | eight |
+----+----------+-------+
我的目标是执行一个查询,在此查询中,它将逐步遍历postcode列,直到找到一个完全匹配的项
假设我的起始查询参数是A1A3E9。基于示例表的预期返回值为6。需要注意的是,每一步,我都会从起始查询参数的末尾删除一个字符
所以首先我会尝试找到A1A3E9的匹配项,然后是A1A3E,然后是A1A3等等
目前,我只是通过一系列IF/ELSE块来实现这一点,如下所示:
如果
存在
从表中选择值
其中邮政编码=:userPost6_1
开始
从表中选择值
其中邮政编码=:userPost6_2
终止
否则如果
存在
从表中选择值
其中邮政编码=:userPost5\u 1
开始
从表中选择值
其中邮政编码=:userPost5_2
终止
否则如果
存在
从表中选择值
其中邮政编码=:userPost4\u 1
开始
从表中选择值
其中邮政编码=:userPost4\u 2
终止
否则如果
存在
从表中选择值
其中邮政编码=:userPost3\u 1
开始
从表中选择值
其中邮政编码=:userPost3\u 2
终止
否则如果
存在
从表中选择值
其中邮政编码=:userPost2_1
开始
从表中选择值
其中邮政编码=:userPost2_2
终止
请注意,我在PHP中使用参数绑定,因此仅在上下文中,我的参数绑定最终如下所示:
$stmt->bindValue:userPost6_1',A1A3E9,PDO::PARAM_STR;
$stmt->bindValue:userPost6_2',A1A3E9,PDO::PARAM_STR;
$stmt->bindValue:userPost5_1',A1A3E,PDO::PARAM_STR;
$stmt->bindValue:userPost5_2',A1A3E,PDO::PARAM_STR;
$stmt->bindValue:userPost4_1',A1A3,PDO::PARAM_STR;
$stmt->bindValue:userPost4_2',A1A3,PDO::PARAM_STR;
$stmt->bindValue:userPost3_1',A1A,PDO::PARAM_STR;
$stmt->bindValue:userPost3_2',A1A,PDO::PARAM_STR;
$stmt->bindValue:userPost2_1',A1,PDO::PARAM_STR;
$stmt->bindValue:userPost2_2',A1,PDO::PARAM_STR;
就性能而言,我没有任何顾虑,因为我在邮政编码列上有一个包含40000多行的索引。我担心的是,这纯粹是一个视觉上的、令人不快的问题
我的问题:有没有更干净的方法来编写此查询?这里有一种方法:
select top (1) t.*
from t
where 'A1A3E9' like t.postcode + '%'
order by t.postcode desc;
唯一的问题是,您的多个if语句可能更快。对于这类问题,获得性能是一个真正的挑战。一种方法使用多个联接:
首先,我将假脱机所有可能匹配的行,例如:
select *
into #matches
from t
where postcode like 'AI%'
这可以在邮政编码上使用索引,因此应该很便宜。然后,对匹配项运行的任何查询都将仅对该子集进行操作。甚至编写一个将邮政编码与文字进行比较的自定义项,例如:
select top 1 *
from #matches
order by dbo.NumberOfMatchingCharacters(postcode,'A1A3E9') desc
select top 1 *
from #matches
order by dbo.NumberOfMatchingCharacters(postcode,'A1A3E9') desc