#sql #sql-server
Вопрос:
У меня есть три таблицы, в первой таблице хранится основная информация о пользователе, во второй таблице хранится информация о пользователе, существующем в каталоге LDAP, а в третьей таблице хранится общая информация обеих таблиц.
ниже приведена структура таблицы
Мне нужно имя из таблицы, если значение не совпадает, затем проверьте другую таблицу. желаемый результат выглядит следующим образом. Я пытался добиться этого, UNION
но в таблице более 70 тысяч записей. это замедляет производительность. Запрос
select Distinct
userInfoID AS 'UserInfoId',
accountName AS 'AccountName',
accountType AS 'AccountType',
privilege AS 'Privilege',
active AS 'IsActive',
org AS 'OrgName',
(L.firstName ' ' L.lastName) AS 'Name',
emailId AS 'EmailAddress'
FROM tbl_UserInfo U
LEFT JOIN tbl_ldapUser L ON L.memberId = U.memberId
UNION
select Distinct
userInfoID AS 'UserInfoId',
accountName AS 'AccountName',
accountType AS 'AccountType',
privilege AS 'Privilege',
active AS 'IsActive',
org AS 'OrgName',
(M.firstName ' ' M.lastName) AS 'Name',
emailId AS 'EmailAddress'
FROM tbl_UserInfo U
LEFT JOIN tbl_Member M ON M.memberId = U.memberId
Комментарии:
1. Если запрос выполняется медленно, укажите его в своем вопросе.
2. Я подозреваю, что a
NOT EXISTS
будет более производительным по сравнению с aUNION
, которому необходимо проверить, что 70k~ строк различны. Показав нам свою попытку, вы очень поможете нам помочь вам. Также необходимо не использовать изображения для текста.3. @GordonLinoff я обновляю вопрос
4. Те
DISTINCT
s вSELECT
s-это просто ненужные накладные расходы. Вы уже указываете, что набор данных должен бытьDISTINCT
связан с использованием вашегоUNION
.5. Пожалуйста, поделитесь планом запроса через brentozar.com/pastetheplan . Полные определения индексов также помогли бы
Ответ №1:
Это невозможно проверить, однако я подозреваю, что это будет гораздо эффективнее. Во-первых , я меняю JOIN
s на an INNER JOIN
, а не на a LEFT JOIN
. Если в строке in tbl_UserInfo
не может быть совпадающих строк в обоих tbl_ldapUser
и tbl_Member
, и вы все еще хотите, чтобы эта строка возвращалась, измените нижний запрос на a LEFT JOIN
(не верхний).
Я удаляю оба DISTINCT
s, так как это просто дополнительные накладные расходы; вы использовали UNION
, поэтому вы уже заявили механизму обработки данных, что вам нужны отдельные строки. Однако я также изменил значение UNION
на a UNION ALL
, что полностью удаляет предложение distinct; вероятно, поэтому ваш запрос был медленным , поскольку DISTINCT
может быть очень дорогим оператором.
Наконец, я использую EXISTS
вместо этого, чтобы проверить, существовала ли строка в tbl_ldapUser
таблице в нижнем запросе. Это останавливает возврат пользователя дважды при сопоставлении с обеими таблицами:
SELECT userInfoID AS UserInfoId,
accountName AS AccountName,
accountType AS AccountType,
privilege AS Privilege,
active AS IsActive,
org AS OrgName,
(L.firstName ' ' L.lastName) AS [Name],
emailId AS EmailAddress
FROM tbl_UserInfo U
JOIN tbl_ldapUser L ON L.memberId = U.memberId
UNION ALL
SELECT userInfoID AS UserInfoId,
accountName AS AccountName,
accountType AS AccountType,
privilege AS Privilege,
active AS IsActive,
org AS OrgName,
(M.firstName ' ' M.lastName) AS Name,
emailId AS EmailAddress
FROM tbl_UserInfo U
JOIN tbl_Member M ON M.memberId = U.memberId
WHERE NOT EXISTS (SELECT 1
FROM tbl_ldapUser L
WHERE L.memberId = U.memberId);
Также обратите внимание, что я удаляю одинарные кавычки вокруг псевдонимов. Это плохая привычка. Одинарные кавычки предназначены для буквенных строк и (даже если они поддерживаются) не должны использоваться для сглаживания. Чтение часто может сбивать с толку, и люди, незнакомые с языком, могут подумать, что синтаксис работает в другом месте. Например ORDER BY 'UserInfoId'
, будет упорядочиваться не по столбцу, использующему псевдоним 'UserInfoId'
, а по буквенной строке 'UserInfoId'
; это означает, что порядок полностью произвольный (так как каждая строка имеет одно и то же значение, 'UserInfoId'
).
Ответ №2:
Вы можете объединиться tbl_ldapUser
, и tbl_Member
перед присоединением это означает, что tbl_UserInfo
запрос будет отправлен только один раз.
Кроме того, если между двумя таблицами нет дубликатов, вы можете перейти к тому UNION ALL
, что будет быстрее.
SELECT
u.userInfoID AS UserInfoId,
u.accountName AS AccountName,
u.accountType AS AccountType,
u.privilege AS Privilege,
u.active AS IsActive,
u.org AS OrgName,
(l.firstName ' ' l.lastName) AS [Name],
l.emailId AS EmailAddress
FROM tbl_UserInfo U
JOIN (
SELECT
l.firstName,
l.lastName,
l.emailId,
l.memberid
FROM tbl_ldapUser l
UNION ALL
-- if there could be duplicates between the two tables change to UNION
SELECT
m.firstName,
m.lastName,
m.emailId,
m.memberid
FROM tbl_Member m
) l ON l.memberId = u.memberId;