首页 > 解决方案 > Mqsyl - 多个左连接

问题描述

我正在尝试改进在线商店管理员端的实时产品搜索。

我们目前正在使用以下查询:

SELECT p.product_id, p.full_title, p.descript, p.cost, p.no_vat, p.high_pic, p.prod_type, count(p.product_id) AS occurence, t.descript AS type_desc, p.available
FROM gdd_product as p, gdd_prodtype as t, gdd_info as i 
LEFT JOIN gdd_keyword as k ON i.product_id = k.product 
WHERE p.prod_type = t.prod_type 
AND i.product_id = p.product_id 
AND replace(concat_ws(p.descript, i.info_search1, i.info_search2, i.info_search3, k.keyword),' ','') 
LIKE '%tool%' 
GROUP BY p.product_id 
ORDER BY occurence DESC, cost ASC LIMIT 30

这可行,但会忽略在 info_search 列中没有条目的任何结果。

所以我尝试改变它,使 gdd_info 被 LEFT JOINed,代码如下:

SELECT p.product_id, p.full_title, p.descript, p.cost, p.no_vat, p.high_pic, p.prod_type,
count(p.product_id) AS occurence, t.descript AS type_desc, p.available 
FROM gdd_product as p, gdd_prodtype AS t
LEFT JOIN gdd_info as i ON p.product_id = i.product_id 
LEFT JOIN gdd_keyword as k ON p.product_id = k.product 
WHERE p.prod_type = t.prod_type 
AND replace(CONCAT_WS(p.descript, i.info_search1, i.info_search2, i.info_search3, k.keyword),' ','')
LIKE '%tool%' 
GROUP BY p.product_id
ORDER BY occurence DESC, cost ASC
LIMIT 30

...但这会引发错误:SQL 错误 (1054): Unknown column 'p.product_id' in 'on Clause'

我究竟做错了什么?

标签: mysqljoinleft-joinmysql-error-1054

解决方案


第一个。不要将标准与 ANSI 标准(ANSI-92 与 ANSI-89)混用。使用 INNER/CROSS/LEFT 连接或,表示法,但不能同时使用。这是不好的形式,最终可能会破裂;也许现在是什么导致了您的 p.product 错误。

SELECT p.product_id, p.full_title, p.descript, p.cost
     , p.no_vat, p.high_pic, p.prod_type
     , count(p.product_id) AS occurence, t.descript AS type_desc
     , p.available 
FROM gdd_product as p
INNER JOIN  gdd_prodtype AS t
 on p.prod_type = t.prod_type 
LEFT JOIN gdd_info as i 
  ON p.product_id = i.product_id 
LEFT JOIN gdd_keyword as k 
  ON p.product_id = k.product 
WHERE replace(CONCAT_WS(p.descript, i.info_search1, i.info_search2, i.info_search3, k.keyword),' ','') 
LIKE '%tool%' 
GROUP BY p.product_id
ORDER BY occurence DESC, cost ASC
LIMIT 30

第二。它省略记录的原因可能是因为与字符串连接的 NULL 是 NULL。然后,您针对永远不会返回结果的 null 搜索字符串。您需要将 i.info_search1... 与空集 '' 合并, coalesce(i.info_earch1,'')依此类推...因此它采用系列中的第一个非空值,然后将字符串与字符串进行比较

replace(CONCAT_WS(
                   coalesce(p.descript,'')
                 , coalesce(i.info_search1,'')
                 , coalesce(i.info_search2,'')
                 , coalesce(i.info_search3,'')
                 , coalesce(k.keyword,'')),' ','')

给我们...

   SELECT p.product_id, p.full_title, p.descript
        , p.cost, p.no_vat, p.high_pic, p.prod_type
        , count(p.product_id) AS occurence, t.descript AS type_desc
        , p.available 
    FROM gdd_product as p
    INNER JOIN  gdd_prodtype AS t
     on p.prod_type = t.prod_type 
    LEFT JOIN gdd_info as i 
      ON p.product_id = i.product_id 
    LEFT JOIN gdd_keyword as k 
      ON p.product_id = k.product 
    WHERE replace(CONCAT_WS(
                    coalesce(p.descript,'')
                  , coalesce(i.info_search1,'')
                  , coalesce(i.info_search2,'')
                  , coalesce(i.info_search3,'')
                  , coalesce(k.keyword,'')),' ','')
          LIKE '%tool%' 
    GROUP BY p.product_id
    ORDER BY occurence DESC, cost ASC
    LIMIT 30

这么想吧……

说 p.descript 存在,但信息不在您的左连接中...所以您将 p.descript 与 null 连接为 null。什么都不会为like空,因此您无法获得任何记录,因为您无法对空值执行相等检查(例如)并期望得到结果。

现在说 p.descript 不存在并且为空,将它与任何为空的内容连接起来再次为空,所以你有相同的结果。

由于 concat_WS 字符串中的任何值都可能为 null,因此我们需要合并所有值以防万一。

现在我们有一个有效的字符串与您的喜欢进行比较,因此当您的字符串与您的喜欢匹配时,您现在将获得结果,而不是当您的 ws_concat 中的列值为空时擦除您的记录。


推荐阅读