Обновление SQL с объединением - PullRequest
2 голосов
/ 23 марта 2012

Есть ли другой быстрый способ сделать обновление, кроме как с помощью соединения?Вот мой запрос, но он немного медленный:

UPDATE @user_dupes
  SET ExternalEmail = ud2.Email
 FROM @user_dupes ud1
INNER JOIN(
SELECT Email, UserName 
  FROM @user_flat_emailtable_dupes
 WHERE EmailType = 2
   AND Email IS NOT NULL AND LEN(Email) > 0
) ud2
ON ud1.UserName = ud2.UserName

Спасибо за любые идеи

Ответы [ 3 ]

4 голосов
/ 23 марта 2012

Пара изменений, в дополнение к тому, что сказал @Adrian ...

UPDATE
  ud1   -- @Adrian's change.  Update the instance that you have already aliased.
SET
  externalEmail = ud2.Email
FROM
  @user_dupes                   AS ud1
INNER JOIN
  @user_flat_emailtable_dupes   AS ud2
    ON ud1.UserName = ud2.UserName
WHERE
      ud2.EmailType = 2      -- Removed sub-query, for layout, doubt it will help performance
  AND ud2.Email IS NOT NULL
  AND ud2.Email <> ''        -- Removed the `LEN()` function

Но, возможно, самое важное в прошлом - обеспечить наличие индексов.JOIN необходим для этой логики (или связанных подзапросов и т. Д.), Поэтому вы хотите, чтобы соединение было производительным.

Индекс (UserName) для @user_dupes и Индекс (EmailType), Электронная почта, имя пользователя) на @user_flat_emailtable_dupes. (Предполагается, что ud2 - это меньшая таблица после фильтрации)

С указанными индексами изменение с LEN(Email) > 0 на Email <> '' может разрешить поиск индекса, а не сканирование.Чем больше ваши столы, тем более очевидным будет это.

4 голосов
/ 23 марта 2012

Если вы используете SQL Server, вы были почти там.Это просто небольшое исправление:

UPDATE ud1 --little fix here!
  SET ExternalEmail = ud2.Email
 FROM @user_dupes ud1
INNER JOIN
(
SELECT Email, UserName 
  FROM @user_flat_emailtable_dupes
 WHERE EmailType = 2
   AND Email IS NOT NULL AND LEN(Email) > 0
) ud2
ON ud1.UserName = ud2.UserName
1 голос
/ 23 марта 2012

Я считаю, что этот запрос будет делать то же самое (хотя вы должны быть уверены, что сформировали @user_flat_emailtable_dupes без повторяющихся имен пользователей). Я не проверял, есть ли у них разные планы выполнения. Похоже, вы дорабатываете нестандартные вводные данные, я упоминаю об этом отчасти потому, что многое из этого делаю и считаю MERGE полезным (тем более полезным для меня, поскольку я не знаю, как работает UPDATE FROM). И отчасти потому, что я никогда не использовал MERGE с переменными. Похоже, что по крайней мере целевая таблица должна быть псевдонимом, или анализатор решает, что @ ud1 является скалярной переменной, и она ломается.

MERGE @user_dupes AS ud1
USING @user_flat_emailtable_dupes AS ud2
    ON emailType = 2 
   AND COALESCE(ud2.email, '') <> ''
   AND ud2.username = ud1.username
WHEN MATCHED THEN UPDATE
    SET externalEmail = ud2.email
    ;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...