Заполнение целевой таблицы из другой таблицы с использованием той же целевой таблицы

#sql #oracle #oracle11g

#sql #Oracle #oracle11g

Вопрос:

У меня есть таблица A, которая и есть несколько других таблиц с рейтингом. Я хочу выполнить преобразование поэтапно. Чтобы выполнить преобразование, я сначала создаю временную таблицу TMP из таблицы A (не все записи. Допустим, X

 CREATE TABLE TMP (EMP_ID NUMBER(9));

SELECT A.EMP_ID FROM A, TMP WHERE A.EMP_ID <>TMP.EMP_ID
  

Но запрос select не возвращает никаких записей. У меня есть 1 миллион записей в таблице. Может кто-нибудь сказать, что я делаю неправильно.

Комментарии:

1. Понятия не имею, о чем вы спрашиваете. Пожалуйста, уточните или улучшите свой пример.

2. Таблица TMP пуста .. Вот почему нет записей. Вы подключаетесь к EMP_ID с помощью TMP table.

3. Что означает «поэтапно»? Я не знаком с этим термином / концепцией. Какое «преобразование» вы делаете — от чего к чему?

Ответ №1:

Вы используете синтаксис соединения, который использовался десятилетия назад. Запятая между вашей таблицей преобразуется в CROSS JOIN . Итак, у вас есть

 SELECT A.EMP_ID 
FROM A
CROSS JOIN TMP 
WHERE A.EMP_ID <> TMP.EMP_ID;
  

Перекрестное соединение объединяет каждую запись в левой таблице с каждой записью в правой таблице, чтобы получить все комбинации. Ваша таблица TMP пуста, поэтому ваш результирующий набор также пуст. (Независимо от того, какое предложение WHERE .)

Используя правильные соединения ANSI, вы можете переписать свой запрос на

 SELECT A.EMP_ID 
FROM A
INNER JOIN TMP ON A.EMP_ID <> TMP.EMP_ID;
  

который делает то же самое (только он применяет критерии объединения напрямую), и ваш результат, конечно, по-прежнему пуст.

Вероятно, вы ищете следующее:

 select emp_id from a
where emp_id not in (select emp_id from tmp);
  

который возвращает вам все emp_id из A, которых (пока) нет в TMP.

Комментарии:

1. Будет ли работать ниже? выберите emp_id из a, где не существует (выберите 1 из tmp, где tmp.emp_id=a.emp_id);

2. Да, ваше NOT EXISTS предложение выполняет то же самое, что и мое NOT IN предложение. Это вопрос личных предпочтений, которые следует использовать. ( NOT IN имеет преимущество в том, что он проще, и недостаток в том, что вы должны убедиться, что не выбираете null внутри подзапроса. Я предполагаю, что tmp.emp_id никогда не может быть нулевым, следовательно, здесь нет проблем.)

3. Спасибо 🙂 Еще один вопрос. Если я добавлю.rownum <= 50000 для таблицы a, увеличит ли это производительность или все равно будет сканировать всю таблицу a.

4. Я не могу сказать наверняка, потому что это зависит от данных и от того, как их видит оптимизатор. Но очень вероятно, что это ускорит выполнение запроса, поскольку процесс поиска строк результатов может быть остановлен после того, как найдено 50000 строк.

Ответ №2:

Ваш запрос не возвращает никаких записей, поскольку tmp он пустой. Когда вы выполняете a cross join , количество записей, которые вы получаете, является произведением записей в двух таблицах. Если у вас есть нулевые записи, то вы получаете нулевые записи.

Итак, я бы просто предложил:

 insert into tmp (emp_id)
    select A.EMP_ID 
    from A;
  

Если вы хотите сделать это, когда tmp не пусто, то вам потребуется дополнительная логика для предотвращения дублирования.