我想知道如何重构这段代码,它似乎不是提取每个字母(A-Z)的每个结果的最佳方式。
我正在考虑一个foreach
语句,例如,foreach %a, %b
等。查询数据库。
$categoryA = query('SELECT * FROM category WHERE category LIKE "A%"',
array('category' => ['category']),
$conn);
$categoryB = query('SELECT * FROM category WHERE category LIKE "B%"',
array('category' => ['category']),
$conn);
这是我的功能
function query($query, $bindings, $conn)
{
$stmt = $conn->prepare($query);
$stmt->execute($bindings);
return $stmt;
}
您可以使用正则表达式而不是LIKE来完成此操作。将查询改为:
SELECT * FROM category WHERE category REGEXP "^[A-Z].*"
进一步解释:正则表达式^[A- z]。*表示以字母a到Z开头,后跟任意数量的字符的任何字符串。
我要注意的是,这种形式的查询,虽然看起来比一堆LIKE查询更优雅,但速度不是很快,因为它不使用索引。这意味着只有当您知道没有很多行要扫描或者您将返回表中的大多数行时才应该使用它。如果这两个条件都不存在,您最好像下面这样连接LIKE语句:
SELECT * FROM category WHERE (category LIKE "A%" OR category LIKE "B%" OR ... )
后一种形式将在类别字段上使用索引(如果存在)。
如果我没弄错的话,你不会想写26次(针对26个字符)差不多的代码吧。这很好,因为这与DRY相反。
你可以这样试试:
$categories = array();
for($i = ord('A'); $i <= ord('Z'); $i++) {
$char = chr($i);
$categories[$char] = $conn->query('SELECT * FROM category WHERE category LIKE "'.$char.'%"')->fetchAll();
}
你就会有一个关联数组,26个字母作为键,你的类别作为值。
遗憾的是,你的查询函数不会为你做这项工作,因为它只会返回true(成功)或false(失败)。
性能:您仍将执行26个查询。这不是性能最好的解决方案,但我想它很容易理解。
也:
(Donald Knuth)过早优化是万恶之源
所以,如果你现在正在学习,只要尝试一下,如果它适合你,不要太担心查询的数量。