如果找不到某些内容,如何编写一个不会失败的连接?

时间:2013-11-01 06:08:16

标签: mysql join

我正在尝试使用SEF网址确定用户所在的页面。它的工作原理如下:

public function getIdsByPath(array $path, $langId) {
    $select = 'SELECT ';
    $from = ' FROM pages t0 ';
    $where = 'WHERE ';

    for($i = 0; $i < count($path); $i++) {
        $ii = $i - 1;
        if($i > 0) {
            $select .= ', ';
            $from .= "LEFT JOIN pages t$i ON (t$i.pid = t$ii.id) ";
            $where .= ' AND ';
        }
        $select .= "t$i.id";
        $where .= "t$i.alias = ?";
    }
    $where .= " AND t0.pid = ?";
    $q = $this->db->prepare($select.$from.$where);

    for($i = 0; $i < count($path); $i++) {
        $q->bindValue($i + 1, $path[$i]);
    }
    $q->bindValue($i + 1, $langId);
    $q->execute();
    return $q->fetch(PDO::FETCH_NUM);
}

此方法的目的是浏览页面层次结构并验证它是否正确。但问题是,由于层次结构显示为SEF URL,如path/to/page/module/action/123explode('/')'前面提到的字符串中的项目不再代表页面,而是其他变量。< / p>

如果我将整个字符串path/to/page/module/action/item/123提供给方法,则查询将找不到任何内容,因为JOIN语句。我试过了其他所有JOIN我也能想到的。所有人都确定,因为没有找到所有的东西,所以没有找到期间。

如果首先通过关键字从URL检测到其他变量,则整个方法可以很好地工作,但这会导致更详细的URL,这是我不想要的。 path/to/page/some-module/edit/123会变为path/to/page/module/some-module/action/edit/item/123。不太好。

有没有办法JOIN的东西,以便MySQL加入它可以和忽略其余的东西?我没有说“如果这个页面层次结构有效,我将告诉你”这个方法应该说明“我将告诉你这个页面层次结构是有效的。”

任何帮助表示感谢。

1 个答案:

答案 0 :(得分:2)

问题在于虽然您使用的是LEFT JOIN,但由于您在WHERE子句中为每个表指定了一个值,因此您强制每个表都有一个记录,这会产生与INNER相同的结果。 JOIN。

因此,改变

$where .= "t$i.alias = ?";

$where .= "(t$i.alias = ? OR t$i.id IS NULL)";

这将允许您利用LEFT JOIN并“跳过”不匹配的表格,同时仍然返回找到的结果。

然后,您的SELECT将返回找到的那些页面的id,然后为与页面不对应的其余值返回null。