代码之家  ›  专栏  ›  技术社区  ›  OM The Eternity

使用多个左联接从不同的表中获取产品详细信息是否是一种好的做法?

  •  1
  • OM The Eternity  · 技术社区  · 14 年前

    我有一个选择查询

        SELECT tbl_product.prod_id,tbl_product.manuf_id, tbl_product.cat_type_id, tbl_product.cat_id, tbl_product.prod_mpn, 
    tbl_product.prod_name, tbl_product.prod_model, tbl_product.prod_retail_price, tbl_product.prod_purchase_price, tbl_product.prod_sp_offer_price, tbl_product.prod_stock_qty, tbl_product.prod_ships_in, 
    tbl_product.prod_rating, tbl_product.prod_preorder, tbl_category_types.cat_type_name, tbl_category_types.cat_type_seo_name, tbl_category.cat_name, tbl_category.cat_seo_name, tbl_product_images.prod_image, tbl_product_details.prod_short_desc, tbl_product_details.prod_long_desc, tbl_product_seo.prod_seo_title, tbl_product_seo.prod_seo_keywords,tbl_product_details.prod_rel_keywords,tbl_product_seo.prod_seo_desc, tbl_product.network_id, tbl_network.network, tbl_network.network_seo_name, tbl_manufacturer.manuf_id, tbl_manufacturer.manuf_name, tbl_manufacturer.manuf_seo_name, tbl_product.prod_preorder_text
    FROM tbl_product    
            LEFT JOIN 
            tbl_category_types ON tbl_category_types.cat_type_id = tbl_product.cat_type_id
            LEFT JOIN 
            tbl_category ON tbl_category.cat_id = tbl_product.cat_id
            LEFT JOIN 
            tbl_product_images ON tbl_product_images.prod_id = tbl_product.prod_id
            LEFT JOIN 
            tbl_product_details ON tbl_product_details.prod_id=tbl_product.prod_id                  
            LEFT JOIN 
            tbl_product_seo ON tbl_product_seo.prod_id = tbl_product.prod_id                    
            LEFT JOIN 
            tbl_network ON tbl_network.network_id = tbl_product.network_id
            LEFT JOIN
            tbl_manufacturer ON tbl_manufacturer.manuf_id = tbl_product.manuf_id                        
            WHERE 
            tbl_product.lang_id = '".$_SESSION["lang_id"]."' AND
            tbl_product.is_comp_phone = 0 AND 
            tbl_product.prod_id = '".$product_id."' AND
            tbl_product_seo.lang_id = '".$_SESSION["lang_id"]."' AND 
            tbl_product_seo.dom_id = '".$_SESSION["domain_id"]."' AND 
            tbl_product_details.lang_id = '".$_SESSION["lang_id"]."' AND 
            tbl_product_details.dom_id = '".$_SESSION["domain_id"]."'  
            LIMIT 1";
    

    我需要用这个查询来获取产品的详细信息,这样做好吗? 或者有更好的选择吗?

    5 回复  |  直到 14 年前
        1
  •  2
  •   Alan Pearce    14 年前

    你问题的答案是肯定的,没关系。

    唯一不好的是它可能容易受到SQL注入的攻击(如果有人可以修改 lang_id domain_id 在会议中,他们会!)

    强烈建议将参数化查询与 PDO ,例如:

    $dbh = new PDO('mysql:dbname=test;host=127.0.0.1','user', 'password'); //assuming mysql
    $sql = "SELECT
        tbl_product.prod_id,
        tbl_product.manuf_id,
        tbl_product.cat_type_id,
        tbl_product.cat_id,
        tbl_product.prod_mpn,
        tbl_product.prod_name,
        tbl_product.prod_model,
        tbl_product.prod_retail_price,
        tbl_product.prod_purchase_price,
        tbl_product.prod_sp_offer_price,
        tbl_product.prod_stock_qty,
        tbl_product.prod_ships_in,
        tbl_product.prod_rating,
        tbl_product.prod_preorder,
        tbl_category_types.cat_type_name,
        tbl_category_types.cat_type_seo_name,
        tbl_category.cat_name,
        tbl_category.cat_seo_name,
        tbl_product_images.prod_image,
        tbl_product_details.prod_short_desc,
        tbl_product_details.prod_long_desc,
        tbl_product_seo.prod_seo_title,
        tbl_product_seo.prod_seo_keywords,
        tbl_product_details.prod_rel_keywords,
        tbl_product_seo.prod_seo_desc,
        tbl_product.network_id,
        tbl_network.network,
        tbl_network.network_seo_name,
        tbl_manufacturer.manuf_id,
        tbl_manufacturer.manuf_name,
        tbl_manufacturer.manuf_seo_name,
        tbl_product.prod_preorder_text
    FROM tbl_product
    LEFT JOIN 
        tbl_category_types ON tbl_category_types.cat_type_id = tbl_product.cat_type_id
    LEFT JOIN 
        tbl_category ON tbl_category.cat_id = tbl_product.cat_id
    LEFT JOIN 
        tbl_product_images ON tbl_product_images.prod_id = tbl_product.prod_id
    LEFT JOIN 
        tbl_product_details ON tbl_product_details.prod_id=tbl_product.prod_id
    LEFT JOIN 
        tbl_product_seo ON tbl_product_seo.prod_id = tbl_product.prod_id
    LEFT JOIN 
        tbl_network ON tbl_network.network_id = tbl_product.network_id
    LEFT JOIN
        tbl_manufacturer ON tbl_manufacturer.manuf_id = tbl_product.manuf_id
    WHERE 
        tbl_product.lang_id = :langid AND
        tbl_product.is_comp_phone = 0 AND 
        tbl_product.prod_id = :productid AND
        tbl_product_seo.lang_id = :langid AND 
        tbl_product_seo.dom_id = :domainid AND 
        tbl_product_details.lang_id = :langid AND 
        tbl_product_details.dom_id = :domainid
    LIMIT 1";
    $stmt = $dbh->prepare($sql)
    $stmt->prepare(':langid', $_SESSION["lang_id"]);
    $stmt->prepare(':productid', $productid);
    $stmt->prepare(':domainid', $_SESSION["domain_id");
    if ($stmt->execute()) {
        $row = $stmt->fetch();
        if ($row === false) {
            // no rows
        } else {
            //do something with row data
        }
    }
    

    我也清理了一下。我碰巧喜欢查询中每列一行,但这是我个人的偏好。

        2
  •  1
  •   AndreKR    14 年前

    是的,没关系。但是请记住,对于MySQL,左连接更难优化,因此为了性能起见,尽可能使用内部连接。

        3
  •  0
  •   Martin Schapendonk    14 年前

    我觉得这是个很好的问题。

        4
  •  0
  •   HLGEM    14 年前

    错误的查询,您在where子句中使用了一些左联接,将它们转换为内部联接。您需要将tbl_product_seo和tbl_product_details的筛选条件移到左联接的ON子句中。

        5
  •  0
  •   mikeq    14 年前

    正如HLGEM所说,在这些表中的某些表上,左连接是没有意义的,只要在where子句中使用它们,优化器就会将它们转换为内部连接。

    原因是,通常在一个表和任何记录中使用左联来获取记录,如果它们存在于第二个表中,则会在第二个表中不存在记录的情况下返回空值。

    使用WHERE子句限制第二个表中的项时,它永远不能返回空值,因此左连接是完全没有意义的