ВСТАВИТЬ ИЗ ВЫБРАТЬ с ГДЕ - ЕСЛИ СУЩЕСТВУЕТ? - PullRequest
0 голосов
/ 06 апреля 2011

У меня есть следующий 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

Я попытался создать этот столбец exists в части SELECT запроса, но это приводит к неправильному подсчету столбцов и делает INSERT fail.

Есть какие-нибудь предложения по достижению этого?

Спасибо.

Ответы [ 4 ]

3 голосов
/ 06 апреля 2011
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
  )
1 голос
/ 06 апреля 2011

Вы можете использовать INSERT IGNORE для продолжения, если ключ существует.Предполагая, что в столбце (ах) есть уникальный ключ.

1 голос
/ 06 апреля 2011

Попробуйте НЕ СУЩЕСТВУЕТ в предложении 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`);
0 голосов
/ 06 апреля 2011

«Insert Ignore» неэффективно, когда тот же SQL повторно выполняется позднее, так как он попытается повторно вставить ВСЕ записи. Вы ДОЛЖНЫ ограничить попытки вставки до минимально возможного количества для лучшей производительности системы.

Использование запросов на дополнительный выбор также неэффективно, «левое соединение» почти всегда быстрее при работе с большими наборами данных. Запросы дополнительного выбора становятся ужасными в предложении SELECT. Используйте 'IFNULL ()' в предложении SELECT вокруг полей из таблицы LEFT JOINed, чтобы указать значения по умолчанию для отсутствующих записей / NULL.

Ответ Томалака работает, но вот чистый пример «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 имеет две конкретные записи: 'womans' и 'mens'. Обратите внимание, что предложение where содержит «pcl_p_pid IS NULL», которое оптимизируется для более быстрой версии «NOT EXISTS IN (Select * From tbl_productcategorylink ...)» при работе с очень большими наборами данных.

Запросы Sub-select выполняют одну из двух вещей:
а) создает временную таблицу.
b) выполняет поиск в выбранной таблице для КАЖДОЙ записи, которая МОЖЕТ быть в ней, когда база данных проходит по основной таблице «От». Это преувеличивает до ужасной производительности, когда в предложении SELECT есть подвыбор.

ЛЕВЫЕ СОЕДИНЕНИЯ используют уже эффективную логику СОЕДИНЕНИЯ, предоставляемую базой данных, с учетом пропущенных записей.

- Дж. Йоргенсон -

...