我的数据库设置如下(简化):
+----------+---------+----------+
| path | val1 | val2 |
+----------+---------+----------+
| a/ | two | cow |
+----------+---------+----------+
| a/b/ | one | cat |
+----------+---------+----------+
| a/b/c | NULL | bat |
+----------+---------+----------+
路径是主键(在实际使用中,更像是Smith / John / Mark / Jr)。
PHP提供路径$mypath = "a/b/c";
是否有一种方法可以构建非空值的结果集,从path
属于$ mypath的所有行中进行选择。
也就是说,要搜索最匹配的键,找到其中的所有非空值,如果有任何空值,则从第二个“最佳”键中获取它们。
EG。 Mysql应检查a / b / c并返回val2 =“bat”,但是看到val1设置为NULL。
因此应该检查a / b /并设置val1 =“one”;
最终结果应为array('val1' => "one", 'val2' => "bat")
。
一位朋友告诉我,有一种“LOCATE”方式,但我无法解决这个问题 这可行吗?
知道MySQL的人可以帮我改写这个问题的标题更具描述性吗?
感谢。
答案 0 :(得分:1)
路径的过滤器是否从左到右严格比较,没有中间匹配?看来情况确实如此,但我想确定一下。
另外,我不确定你的逻辑基础/规则是什么,以确定应该选择III,但是这里有一个例子,如果val2
是一个数字列,那将会起作用:
CREATE PROCEDURE `test`(IN phpPath VARCHAR(50))
BEGIN
SELECT A.val1, B.val2
FROM
(SELECT val1 FROM `yourtablehere`
WHERE val1 IS NOT NULL AND instr(phpPath, path) = 1
ORDER BY length(path) DESC) A
, (SELECT val2 FROM `yourtablehere`
WHERE val2 IS NOT NULL AND instr(phpPath, path) = 1
ORDER BY length(path) DESC) B
LIMIT 1
END
你能测试一下,如果你得到了理想的结果,请告诉我们吗? (同样,首先假设列val2
是数字)
我还建议您在代码中使用存储过程而不是嵌入式SQL命令,因此我也包含了create语法。 使用存储过程和正确的参数绑定可以帮助您对抗SQL注入。要注意,SELECT
命令需要一个参数/变量来包含包含行的基础。
[编辑]我知道这些代码太优雅了,但是你可以尝试一下这个代码,看看它是否有效?尝试用不同的场景测试它......
答案 1 :(得分:0)
LOCATE(x,y)
返回x
中y
的位置(如果x不是子字符串,则返回0)。如果x
是y
的前缀,则为LOCATE(x,y) = 1
,这是您用作条件的前缀。如果您不希望'Smith / Jo'匹配'Smith / John / Mark / Jr',那么您需要在条件中添加一些内容以防止此匹配,例如将'/'连接到路径列值,这将影响性能,因为MySQL将无法使用path
列上的任何索引。至于找到最长的路径匹配(“最好”是一个非常非描述性的词,通常应该避免),你可以使用排序来获得最长的,LIMIT
来忽略更短的结果。
SELECT val2
FROM tbl
WHERE (path = ? OR LOCATE(CONCAT(path, '/'), ?) = 1)
AND val1 IS NOT NULL
ORDER BY STRLEN(path)
LIMIT 1
答案 2 :(得分:0)
总结:
仅使用SQL可能无法按要求执行操作
但是,SQL可以从匹配的键中获取多维数组,而PHP可以将其缩小为一个数组。
如果有人可以改进这一点,只使用SQL(如发布的问题),我们将不胜感激。
SQL:
SELECT * FROM `mytable` WHERE `path` = '$mypath'
OR (LOCATE(`path`, '$mypath') = 1 AND RIGHT(`path`, 1) = '/')
ORDER by length(`page`) desc;
PHP:
$results = mysql_query(... sql ...);
$pg = array();
foreach(array_keys($results[0]) as $key)
foreach($results as $result)
if ($result[$key]){ $pg[$key] = $result[$key]; continue 2; }
您可以在http://codepad.org/UnyEZJ6a
的实践中看到这一点注意:
希望这可以帮助别人!