Является ли хорошей практикой использование нескольких левых соединений для получения сведений о продукте из разных таблиц? - PullRequest
1 голос
/ 18 ноября 2010

У меня есть запрос на выборку как

    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 ]

2 голосов
/ 18 ноября 2010

Ответ на ваш вопрос: да, все в порядке.

Единственная плохая вещь - это то, что он потенциально уязвим для внедрения 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
    }
}

Я также немного его очистил.Мне нравится одна строка на столбец в запросе, но это личное предпочтение.

1 голос
/ 18 ноября 2010

Да, все в порядке. Но имейте в виду, что для MySQL LEFT JOINs сложнее оптимизировать, поэтому для повышения производительности используйте INNER JOINs, где это возможно.

0 голосов
/ 19 ноября 2010

Как говорит HLGEM, левые объединения на некоторых из этих таблиц не имеют смысла, как только вы используете их в предложении where, Оптимизатор превратит их в ВНУТРЕННИЕ СОЕДИНЕНИЯ.

Причина в том, что вы обычно используетеLEFT JOIN для получения записей в одной таблице и любых записей, если они существуют во второй таблице, это вернет NULLS, если во второй таблице нет записей.

При использовании предложения WHERE для ограничения элементов во второй таблицетаблица, она никогда не сможет вернуть NULLS, поэтому LEFT JOINS совершенно бессмысленно

0 голосов
/ 19 ноября 2010

Неверный запрос, вы преобразовали некоторые из этих левых объединений во внутренние объединения, используя их в предложении where.Необходимо переместить условия фильтрации для tbl_product_seo и tbl_product_details в предложение ON левых соединений.

0 голосов
/ 18 ноября 2010

Похоже, хороший запрос для меня.

...