2011-04-06 49 views
0

我有以下INSERT從SELECT處插入INSERT - 如果存在?

INSERT INTO `tbl_productcategorylink` 
(`pcl_p_id`, `pcl_cat_id`, `pcl_orderby`) 
    SELECT 
    `p_id` AS pcl_p_id, 
    (SELECT `cat_id` FROM `tbl_categories` WHERE 
     CASE 
      WHEN `tbl_products`.`p_gender` = 'female' THEN 
       `cat_url_tag` = 'womens' 
      ELSE 
      `cat_url_tag` = 'mens' 
     END 
    LIMIT 1) AS pcl_cat_id, 
    1 AS pcl_orderby 
FROM `tbl_products` 
WHERE `tbl_products`.`p_gender` = 'female' OR `tbl_products`.`p_gender` = 'male'; 

這是添加鏈接類別和產品之間,p_gender設定爲「男性」任何產品都加入到「男子」類別,同樣爲「女'類。

如何才能做到這一點,但只有當某一行尚不存在給定的產品?

我基本上需要的東西添加到我的WHERE條款,以確定是否已存在某行:

AND `exists` IS NULL 

我試圖創建查詢的SELECT部分原因exists列,但是這會搞砸列數並使INSERT失敗。

對此有何建議?

謝謝。

回答

3
INSERT 
    tbl_productcategorylink 
    (pcl_p_id, pcl_cat_id, pcl_orderby) 
SELECT 
    p.p_id, c.cat_id, 1 
FROM 
    tbl_products p 
    INNER JOIN tbl_categories c ON c.cat_url_tag = CASE p.p_gender 
               WHEN 'female' THEN 'womens' 
               ELSE 'mens' END 
WHERE 
    p.p_gender IN ('female', 'male') 
    AND NOT EXISTS (
    SELECT 1 FROM tbl_productcategorylink WHERE pcl_p_id = p.p_id 
) 
+0

非常漂亮託默勒格 - 感謝 – 2011-04-07 08:22:44

+0

略有修改到'不EXISTS'是這樣的'AND pcl_cat_id = C。作爲產品的cat_id'可能已經在表tbl_productcategorylink中,但是在另一個類別中。再次感謝。 – 2011-04-07 10:11:43

+0

@jakenoble:是的,我想添加類似的東西,但後來決定我無法確定這對你是對還是錯。顯然,你可以自己弄清楚。 :-)我的觀點更多的是你可以加入表達式,這使得SQL語句比原來的語句簡單和直接。 – Tomalak 2011-04-07 16:47:53

1

嘗試不要在where子句中存在:

INSERT INTO `tbl_productcategorylink` 
(`pcl_p_id`, `pcl_cat_id`, `pcl_orderby`) 
    SELECT 
    `p_id` AS pcl_p_id, 
    (SELECT `cat_id` FROM `tbl_categories` WHERE 
     CASE 
      WHEN `tbl_products`.`p_gender` = 'female' THEN 
       `cat_url_tag` = 'womens' 
      ELSE 
      `cat_url_tag` = 'mens' 
     END 
    LIMIT 1) AS pcl_cat_id, 
    1 AS pcl_orderby 
FROM `tbl_products` 
WHERE `tbl_products`.`p_gender` = 'female' OR `tbl_products`.`p_gender` = 'male' 
    AND NOT EXISTS (SELECT * FROM `tbl_productcategorylink` WHERE `pcl_p_id` = `tbl_products`.`p_id`); 
1

你可以使用INSERT IGNORE繼續如果鍵存在。假設列上有一個唯一的鍵。

0

當稍後重新執行相同的SQL時,「Insert Ignore」效率不高,因爲它將嘗試重新插入所有記錄。您必須限制嘗試插入儘可能最小的數量,以獲得最佳系統性能。

使用子選擇查詢的效率也很低,使用大型數據集時「LEFT JOIN」幾乎總是更快。子選擇查詢在SELECT子句中變得可怕。在LEFT JOINed表的字段周圍的SELECT子句中使用'IFNULL()',爲缺失/ NULL記錄提供默認值。

Tomalak的答案很有用,但這是一個純粹的'LEFT JOIN'示例。

INSERT INTO tbl_productcategorylink (p_pid, pcl_cat_id, pcl_orderby) 
SELECT prod.p_pid, IFNULL(cat.cat_id,0), 1 AS pcl_orderby 
    FROM tbl_products     AS prod 
    LEFT JOIN tbl_categories   AS cat ON cat.cat_url_tag = IF(prod.p_gender='female','womans','mens') 
    LEFT JOIN tbl_productcategorylink AS pcl ON pcl.pcl_p_id = prod.p_id 
WHERE prod.p_gender IN ('female','male') 
    AND pcl.pcl_p_id IS NULL -- Optimizes to faster "NOT EXISTS IN (Select ... From pcl)" 

這個重寫是假設tbl_categories有2個特定的記錄:'womans'和'mens'。 請注意,'where'子句包含「pcl_p_pid IS NULL」,它在處理非常大的數據集時優化爲「NOT EXISTS IN(選擇*來自tbl_productcategorylink ...)」的更快版本。

子選擇查詢執行以下兩項操作之一:
a)創建一個臨時表。
b)當數據庫遍歷主'From'表時,執行'查找'到可能存在的每個記錄的子選擇表中。當子選擇在'SELECT'子句中時,這被誇大成可怕的表現。

LEFT JOIN使用數據庫提供的已有效的JOIN邏輯,並允許缺少記錄。

- J·喬根森 -