在连接表

时间:2016-04-04 10:04:36

标签: sql join sql-like concat

我试图解决这个问题一段时间后没有找到解决方案。

我从一个装满移动设备的表中读取并列出它们,并为用户提供了搜索每个Movile设备名称和用户名列表的可能性。

这是我的代码:

        SELECT
        *
    FROM
        tbl_mobdev
    LEFT JOIN
        tbl_mobdev_type ON mobdev_type_id = mobdev_type
    LEFT JOIN
        tbl_marke ON marke_id = mobdev_type_marke
    LEFT JOIN
        tbl_user ON tbl_user.id = mobdev_user
    WHERE
        CONCAT(tbl_marke.marke_name,' ',tbl_mobdev_type.mobdev_type_bezeichnung) LIKE '%".$_POST['marke_name']."%'
    AND
        CONCAT(tbl_user.name,' ',tbl_user.vorname) LIKE '%".$_POST['user']."%'
    AND
        mobdev_aktiv = '1'
    ORDER BY
        ".$_GET['sort']." ".$_GET['sort2']."

只要tbl_mobdev.mobdev_user包含用户ID,一切都按预期工作,而不包含用户ID的表行则被省略。

任何解决方案吗?

编辑:将“过滤器”放在tbl_user的LEFT JOIN中的解决方案不起作用。将显示类似以下每行结果的SQL。 如果LIKE包含某些内容,则不会连接不匹配的结果,则不会过滤该行。

SELECT mobdev_id, mobdev_type_bezeichnung, marke_name, tbl_user.name AS  user_name, tbl_user.vorname AS user_vorname
FROM tbl_mobdev
LEFT JOIN tbl_mobdev_type ON mobdev_type_id = mobdev_type
LEFT JOIN tbl_marke ON marke_id = mobdev_type_marke
LEFT JOIN tbl_user ON tbl_user.id = mobdev_user
AND CONCAT( tbl_user.name, ' ', tbl_user.vorname ) LIKE '%%'
WHERE CONCAT( tbl_marke.marke_name, ' ', tbl_mobdev_type.mobdev_type_bezeichnung ) LIKE '%%'
AND mobdev_aktiv = '1'
ORDER BY marke_name ASC 
LIMIT 0 , 30

Edit2:将SQL设置为以下内容并没有改变行为。

SELECT mobdev_id, mobdev_type_bezeichnung, marke_name, tbl_user.name AS user_name, tbl_user.vorname AS user_vorname
FROM tbl_mobdev
LEFT JOIN tbl_mobdev_type ON mobdev_type_id = mobdev_type
LEFT JOIN tbl_marke ON marke_id = mobdev_type_marke
LEFT JOIN tbl_user ON tbl_user.id = mobdev_user
AND CONCAT( tbl_user.name, ' ', tbl_user.vorname ) LIKE '%G%'
WHERE CONCAT( tbl_marke.marke_name, ' ', COALESCE( tbl_mobdev_type.mobdev_type_bezeichnung, '' ) ) LIKE '%%'
AND mobdev_aktiv = '1'
ORDER BY marke_name ASC 
LIMIT 0 , 30

没有匹配$ _POST ['user']的行仍然没有被过滤掉。

我上传了一个带有模糊名称的行为的示例图片,左边的图片是一个没有任何过滤器的选择,右图片是一个具有实际用户名的选择(模糊了,但它与mobdev_id中的名称完全相同'3 ”。

http://fs5.directupload.net/images/160404/tmdbyzws.png

正如您所看到的,其他五行仍然存在,只是没有连接。我希望它们完全消失,因为它们与过滤器不匹配。

Edit3:嗯,我现在做到了......遗憾的是,使用PHP非常脏。我只是在这里留下代码,如果有人想出更好的解决方案,请告诉我。

$query = "
    SELECT
        mobdev_id,
        mobdev_type_bezeichnung,
        marke_name,
        tbl_user.name AS user_name,
        tbl_user.vorname AS user_vorname
    FROM
        tbl_mobdev
    LEFT JOIN
        tbl_mobdev_type ON mobdev_type_id = mobdev_type
    LEFT JOIN
        tbl_marke ON marke_id = mobdev_type_marke
    LEFT JOIN
        tbl_user ON tbl_user.id = mobdev_user
    WHERE
        CONCAT(tbl_marke.marke_name,' ',tbl_mobdev_type.mobdev_type_bezeichnung) LIKE '%".$_POST['marke_name']."%'
        ";
if($_POST['user'])
{
    $query .= "
        AND
            CONCAT(tbl_user.name,' ',tbl_user.vorname) LIKE '%".$_POST['user']."%'
        ";
}
$query .= "
    AND
        mobdev_aktiv = '1'
    ORDER BY
        ".$_GET['sort']." ".$_GET['sort2']."
    ";

1 个答案:

答案 0 :(得分:1)

问题出在

    CONCAT(tbl_user.name,' ',tbl_user.vorname) LIKE '%".$_POST['user']."%'

您在tbl_user上的LEFT JOIN将允许主查询返回,而不管该行中是否有值。但是,特定的WHERE子句行有效地覆盖了这一点;如果tbl_user.name或tbl_user.vorname为null,则结果将始终为false。

如果我需要做类似的事情,我经常将测试放入JOIN语句的ON子句中。这样它就会过滤JOINed表所在的位置,但不会导致问题。

示例查询文本应确保tbl_user在需要时进行过滤,但在没有指定任何内容时则不会过滤 -

SELECT
    md.mobdev_id, 
    mdt.mobdev_type_bezeichnung, 
    m.marke_name, 
    u.name AS  user_name, 
    u.vorname AS user_vorname
FROM
    tbl_mobdev md
        LEFT JOIN tbl_mobdev_type mdt
            ON mdt.mobdev_type_id = md.mobdev_type
        LEFT JOIN tbl_marke m
            ON m.marke_id = mdt.mobdev_type_marke
        LEFT JOIN tbl_user u
            ON u.id = md.mobdev_user
            AND CONCAT(u.name,' ',u.vorname) LIKE '%".$_POST['user']."%'
WHERE
    CONCAT(m.marke_name,' ',COALESCE(mdt.mobdev_type_bezeichnung,'')) 
            LIKE '%".$_POST['m.marke_name']."%'
    AND md.mobdev_aktiv = '1'
ORDER BY
    ".$_GET['sort']." ".$_GET['sort2']."

两个旁白 -

  • 正如Rene M.上面所说,此代码是一个SQL注入漏洞。由于目前的应用可能是安全的,但我仍然不会推出它;有人拿这个应用程序或代码片段然后在没有进行全面审核的情况下将其移到网上的可能性并不是微不足道的,然后你就会遇到问题。练习正确 - 不要在代码中留下SQL注入漏洞。
  • 请为您的表名添加别名!对于每个字段引用,每个表名都写满的查询会使它非常笨重。