2012-04-06 2 views
1

Мой запрос довольно прост:сравнения Принятие запроса возрасты

select a.ID, a.adres, a.place, a.postalcode 
from COMPANIES a, COMPANIES b 
where a.Postcode = b.Postcode 
and a.Adres = b.Adres 
and ( 
select COUNT(COMPANYID) 
from USERS 
where COMPANYID=a.ID 
)>( 
select COUNT(COMPANYID) 
from USERS 
where COMPANYID=b.ID 
) 

База данных: SQL Server 2008 R2

То, что я пытаюсь сделать: Таблица КОМПАНИЯМИ содержит двойные записи. Я хочу знать те, которые связаны с большинством пользователей. Поэтому мне нужно изменить только внешние ключи. (Я уже знаю идентификаторы удвоений)

Прямо сейчас это занимает много времени. Мне было интересно, если можно было бы сделать быстрее

+2

у вас есть индексы, определенные на объединение и где положение колонок? – Oded

+0

Да идентификатор является первичным ключом компаний и CompanyID индексируется, поскольку мы используем соединение довольно часто для поиска пользователей. –

+0

И поля 'Postcode' и' Adres' на self join? – Oded

ответ

3

Пробуйте эту версию. Это должно быть только немного быстрее. COUNT довольно медленный. Я добавил a.ID <> b.ID, чтобы избежать нескольких случаев раньше.

select a.ID, a.adres, a.place, a.postalcode 
from COMPANIES a INNER JOIN COMPANIES b 
ON 
a.ID <> b.ID 
and a.Postcode = b.Postcode 
and a.Adres = b.Adres 
and ( 
select COUNT(COMPANYID) 
from USERS 
where COMPANYID=a.ID 
)>( 
select COUNT(COMPANYID) 
from USERS 
where COMPANYID=b.ID 
) 

FROM ... INNER JOIN ... ON ... является предпочтительной конструкцией SQL для объединения таблиц. Это может быть и быстрее.

+0

Немного быстрее? Время для моего теста было сокращено с 2 минут до 9 секунд. Экономия 92,5%. Теперь протестируйте его в полной версии. _Просто сообщить: вам не хватает 'и' между 'b.ID' и' a.postcode'_ –

+2

@WouterVerleur. Это дополнение «a.ID <> b .ID ", что привело к отбрасыванию самосогласований и, следовательно, гораздо меньшему счету. –

+0

В соответствии с @ NikolaMarkovinović, его идентификатор проверяет, что ускоряет запрос, но я повторно повторяю рекомендацию использовать внутреннее соединение ... вместо, а не где - он делает ваши запросы более ясными (предложение where - это о фильтрации данные и соединения между таблицами являются отдельными) – kaj

0

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

insert into @CompanyCount (ID, IDCount) 
select COMPANYID, COUNT(COMPANYID) 
from USERS 
group by COMPANYID 

Тогда ваш главный вопрос:

select a.ID, a.adres, a.place, a.postalcode 
from COMPANIES a 
    inner join @CompanyCount aCount on aCount.ID = a.ID 
    inner join COMPANIES b on b.Postcode = a.Postcode and b.Adres = a.Adres 
    inner join @CompanyCount bCount on bCount.ID = b.ID and aCount.IDCount > bCount.IDCount 

Если вы хотите, чтобы все экземпляры a, даже если нет соответствующих b то вы должны были бы иметь left outer join с до b и bCount ,

Однако вы должны смотреть на план запроса - какие показатели вы используете - вы, вероятно, хотите, чтобы иметь их на ID с и Postcode и Adres полей, как минимум, так как вы вступающих на них.

+0

Пробовал: Дает мне всего 2 строки, а оригинал дает мне 34 строки, хотя ничего, кажется, не хватает. Я только хочу сравнить 'a', который имеет аналог' b' (только удваивается). –

+0

Так как у @Michas есть рабочий ответ (я его поддержал), я не буду этого делать - мне нужно больше информации о ваших данных, возможно, это было написано без моего тестирования, оно работает в теории:) Одна вещь, которую я бы посоветовал, - избегать столбцов с именем «ID» - если они специфичны, как ваш CompanyID, это уменьшает путаницу в запросе – kaj

+0

Если честно, я стараюсь избегать полевых имен короче 5 символов. Но я не тот, кто создал базу данных. И тот, который создал базу данных еще в 2000 году. Работа, которую я делаю, - это переход на новую систему (с полностью новой базой данных, разработанной мной). Спасибо за совет. Я буду помнить об этом. –

0
  1. построить индекс по почтовому индексу и ADRES

  2. база данных, вероятно, выполняет подзапросы для каждой строки. (Просто угадайте здесь, очень хорошо это в плане объяснения. Если это так, вы можете переписать запрос, чтобы присоединиться к встроенным представлениям (обратите внимание, что это будет выглядеть в oracle hop, он также работает на сервере sql):

    select distinct a.ID, a.adres, a.place, a.postalcode 
    from 
        COMPANIES a, 
        COMPANIES b, 
    (
        select COUNT(COMPANYID) cnt, companyid 
        from USERS 
        group by companyid) cntA, 
    (
        select COUNT(COMPANYID) cnt, companyid 
        from USERS 
        group by companyid) cntb 
    where a.Postcode = b.Postcode 
    and a.Adres = b.Adres 
    and a.ID<>b.ID 
    and cnta.cnt>cntb.cnt 
    
+0

Это не работает в SQL Результат: Msg 8120, уровень 16, состояние 1, строка 6 'Столбец USERS.COMPANYID 'недопустим в списке выбора, потому что он не содержится либо в агрегатной функции, либо в предложении GROUP BY. –

+0

Прошу простить группу. Добавлено. Вероятно, содержит еще один или несколько опечаток .. не пробовал это в базе данных –

+0

Я не смогу проверить его до вторника, но я посмотрю, сработает ли он тогда. Мы оба могли бы немного поучиться у него? –

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