Вставить запись в таблицу, если запись не существует в другой таблице - с дополнительным поворотом

Привет всем, могучие SQLsuperheros .. Может ли кто-нибудь спасти меня от неминуемой катастрофы и разорения?

Я работаю с Microsoft Access SQL. Я хотел бы выбрать записи в одной таблице (table1), которые не отображаются в другой (table2) .., а затем вставить новые записи в table2, основанные на записях в table1, следующим образом:

[table1] file_index: имя файла

[table2] индекс_файла: имя_звёздочки

Я хочу:

Выберите все записи из таблицы1, где [имя_файла] похоже на aud и соответствующее значение [file_index] не существует в таблице2 с полем with [знаменитость] = 'Audrey Hepburn'

После этого выбора я хочу вставить новую запись в [table2]

[file_index] = [table1]. [file_index] [Celeb_name] = 'Одри Хепберн'

Между [file_index] в [table1] и [table2] существует отношение «один ко многим». Одна запись в [table1], ко многим в [table2].

Большое спасибо


person bonzo46    schedule 03.02.2010    source источник


Ответы (4)


Подойдет ли это? Очевидно, добавьте квадратные скобки и прочее. Не слишком в Access.

INSERT INTO table2 (file_index, celeb_name)
SELECT file_index, 'Audrey Hepburn'
FROM table1
WHERE filename = 'aud'
  AND file_index NOT IN (SELECT DISTINCT file_index 
                         FROM table2 
                         WHERE celeb_name = 'Audrey Hepburn')
person Tor Valamo    schedule 03.02.2010
comment
Tor - вы действительно могущественный бог SQL, как следует из вашего имени. Большое спасибо. Это сработало - person bonzo46; 04.02.2010
comment
NOT IN плохо оптимизирован в Jet / ACE, так как он часто не использует индексы с обеих сторон (или в некоторых случаях с обеих сторон). И OUTER JOIN будет намного более надежным, поскольку он всегда использует индексы, если объединенные поля индексируются. - person David-W-Fenton; 04.02.2010
comment
@ David-W-Fenton - Любой, кто использует Access и ожидает производительности, действительно должен поискать в другом месте ...;) - person Tor Valamo; 04.02.2010
comment
@ David-W-Fenton - Я имею в виду, что вы используете Access для настольных приложений, а не для кластера серверов с петабайтами данных. И поэтому любая задержка в 4 мс, вызванная этим подзапросом, никогда не будет и не будет проблемой. Также обратите внимание, что Access имеет ограничение на размер базы данных 2 ГБ, поэтому я не вижу большого количества сценариев, когда это займет некоторое время. - person Tor Valamo; 05.02.2010
comment
Это дурацкий запрос. Помог добраться туда, где мне нужно быть. Спасибо. - person usumoio; 28.02.2013

Как я уже сказал в комментариях, NOT IN плохо оптимизирован Jet / ACE, и обычно более эффективно использовать OUTER JOIN. В этом случае, поскольку вам нужно фильтровать внешнюю сторону соединения, вам понадобится подзапрос:

  INSERT INTO photos_by_celebrity ( ORIG_FILE_INDEX, celebrity_name )
  SELECT tblOriginal_Files.ORIG_FILE_INDEX, 'Audrey Hepburn'
  FROM tblOriginal_Files 
    LEFT JOIN (SELECT DISTINCT ORIG_FILE_INDEX  
                  FROM photos_by_celebrity 
                  WHERE celebrity_name = 'Audrey Hepburn') AS Photos
    ON tblOriginal_Files.ORIG_FILE_INDEX = Photos.ORIG_FILE_INDEX
  WHERE Photos.ORIG_FILE_INDEX Is Null;

(это может быть не совсем правильно - я ужасно пишу SQL вручную, особенно правильно разбираюсь в синтаксисе JOIN)

Однако я должен сказать, что мне интересно, будет ли это вставлять слишком много записей (и то же самое относится к версии NOT IN).

person David-W-Fenton    schedule 04.02.2010

В исходном вопросе я изменил имена таблиц и полей и вставил квадратные скобки, чтобы их было легче читать.

Ниже приведен последний оператор SQL, работавший в формате MS Access. Отличный результат, еще раз спасибо Tor !!

INSERT INTO photos_by_celebrity ( ORIG_FILE_INDEX, celebrity_name )

SELECT tblOriginal_Files.ORIG_FILE_INDEX, 'Audrey Hepburn' AS Expr1

FROM tblOriginal_Files

WHERE (((tblOriginal_Files.ORIG_FILE_INDEX) Not In (SELECT DISTINCT ORIG_FILE_INDEX 

                         FROM photos_by_celebrity  

                         WHERE celebrity_name = 'Audrey Hepburn')) AND ((tblOriginal_Files.ORIGINAL_FILE) Like "*aud*"));
person bonzo46    schedule 04.02.2010
comment
Извините, мое первоначальное редактирование было совершенно неправильным, просто неосторожный перевод с моей стороны. Я просто исправил это и заменил свой запрос на приведенный выше. - person bonzo46; 04.02.2010

Вы можете использовать NOT Exists

Я считаю, что это лучший способ с точки зрения производительности.

Следующим образом:

INSERT INTO table2 (file_index, celeb_name)
SELECT file_index, 'Audrey Hepburn'
FROM table1
WHERE filename = 'aud'
  AND NOT Exists (SELECT file_index 
                         FROM table2 
                         WHERE celeb_name = 'Audrey Hepburn')
person i Smart Learning    schedule 26.06.2020