2013-03-13 3 views
0

В SQL Server 2008 У меня есть таблица, содержащая данные из загружаемой деятельности на нашем веб-сайте. Я создал инструмент для ручной сопоставления каждой компании из таблицы загрузки веб-страниц в учетные записи в нашей базе данных клиентов. Не все загрузчики фактически принадлежат компании-клиенту. Эти не-клиенты сопоставляются с учетной записью по умолчанию.Более эффективный выбор

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

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

Проблема возникает, когда я хочу перечислить эти компании из webDownloadTable, которые не соответствуют существующим учетным записям (или учетной записи по умолчанию), то есть: не существует в accountMatchingTable.

Наиболее важные столбцы в webDownloadTable являются:

webDownloadTable(
ID int not null 
webCompanyName varchar(200), 
webCountryName varchar(200), 
item integer(8), 
......, 
... 
); 

Первичный ключ ID.

Совпадение таблица выглядит следующим образом:

accountMatchingTable(
AccountID int(8), 
matchedCompanyName varchar(200), 
matchedCountryName varchar(200), 
......, 
... 
); 

Первичный ключ (AccountID, matchedCompanyName, matchedCountryName).

Таблицы, по-видимому, хорошо проиндексированы.

Я сделал SQL-выбор, который действительно работает, но по мере роста числа строк он будет очень медленным. Он выбирает верхние 15 рядов, где название компании + страна не соответствует:

SELECT DISTINCT TOP 15 webCompanyName, webCountryName 
FROM webDownloadTable 
WHERE (webCompanyName + webCountryName NOT IN 
     (SELECT matchedCompanyName + matchedCountryName FROM accountMatchingTable) /*The combination of name and country from the matching table*/ 
) 
    AND 
    (webCompanyName + ' ' NOT IN 
     (SELECT matchedCompanyName + matchedCountryName FROM accountMatchingTable) /*The combination of name and an empty space from the matching table (see §. below)*/ 
    ) 
ORDER BY webCompanyName, webCountryName; 

§. Вам нужна эта часть, чтобы выбрать те случаи, когда поле страны открыто (см. Объяснение выше).

Есть ли кто-нибудь, кто может помочь мне создать более эффективный выбор?

+0

«Таблицы, по-видимому, хорошо проиндексированы». Какие еще индексы находятся в аккаунтеMatchingTable? (В настоящее время похоже, что существующий запрос не может использовать какие-либо индексы в этой таблице.) –

+0

Поля, используемые в выборе, также индексируются. –

ответ

3

Как насчет удалив два подзапросы, как так:

SELECT DISTINCT TOP 15 a.webCompanyName, a.webCountryName 
FROM webDownloadTable a 
    LEFT OUTER JOIN accountMatchingTable b 
    ON a.webCompanyName + a.webCountryName = b.webCompanyName + b.webCountryName 
    OR a.webCompanyName + ' ' = b.webCompanyName + b.webCountryName 
WHERE b.webCompanyName IS NULL 
ORDER BY webCompanyName, webCountryName 
+0

Согласен, делая LEFT-JOIN, а затем поиск нулевого значения намного эффективнее, чем выполнение подвыборок, применяемых к каждой попытке строки. – DRapp

+0

@DaveSexton - вы пропустили предложение 'ORDER BY' - без него,' TOP Не имеет смысла. – Bridge

+0

@Bridge - добавлено ORDER BY –

1

Я думаю, что это будет делать трюк:

SELECT DISTINCT TOP 15 webCompanyName, 
         webCountryName 
FROM webDownloadTable 
     LEFT OUTER JOIN accountMatchingTable 
     ON webDownloadTable.webCompanyName = accountMatchingTable.matchedCompanyName 
      AND (webDownloadTable.webCountryName = accountMatchingTable.matchedCountryName 
        OR accountMatchingTable.matchedCountryName = ' ') 
WHERE accountMatchingTable.matchedCompanyName IS NULL 
ORDER BY webCompanyName, 
      webCountryName; 

Я не уверен в DISTINCT TOP 15 хотя - это может быть лучше выполнить выделение в подзапросе, а затем выбрать TOP 15 или использовать разделение функции ранжирования по двум вашим значениям.

1

Вы можете попробовать использовать пункт NOT EXISTS, например, так:

SELECT DISTINCT TOP 15 webCompanyName, webCountryName 
FROM webDownloadTable d 
WHERE NOT EXISTS 
(SELECT 1 
FROM accountMatchingTable m 
WHERE m.matchedCompanyName = d.webCompanyName AND 
     m.matchedCountryName in (d.webCountryName, ' ') 
) 
ORDER BY webCompanyName, webCountryName; 

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

+0

+1 - Я тоже пошел на отдельные столбцы. Стыдно принятый ответ не делает :-( – Bridge

Смежные вопросы