2012-04-06 150 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

你有上定義的索引的連接和where子句中的列? – Oded 2012-04-06 08:25:48

+0

是,該ID是公司的主鍵和companyid被索引,因爲我們使用的連接經常搜索用戶。 – 2012-04-06 08:27:23

+0

並且自加入的'Postcode'和'Adres'字段? – Oded 2012-04-06 08:28:02

回答

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%。現在測試它的完整版本.. _Just to inform you:You's missing a and' between between'b.ID' and'a.postcode'_ – 2012-04-06 09:16:42

+2

@WouterVerleur它增加了「a.ID <> b .ID「導致丟棄自我匹配,因此很少計數。 – 2012-04-06 09:19:29

+0

根據@NikolaMarkovinović,它的ID檢查,加速查詢,但我會重新建議使用內部連接......而不是在哪裏 - 它使你的查詢更清晰(where子句是關於過濾數據和表之間的連接是分開的) – kaj 2012-04-06 09:26:16

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 s到bbCount

但是你需要看看查詢計劃 - 其索引你使用 - 你可能希望有他們在ID S和因爲你加入他們的PostcodeAdres領域最低。

+0

試過: 給我只有2行,原來給了我34行,但似乎沒有丟失。 我只想比較'a',它有一個對應的'b'(只有雙打)。 – 2012-04-06 09:06:00

+0

因爲@Michas已經給你一個工作答案(我已經提出了這個答案),我不會追求這個 - 我需要更多關於你的數據的信息 - 這可以在沒有我的測試的情況下寫出來,它理論上有效: - )我建議的一件事是避免使用名爲「ID」的列 - 如果它們像您的CompanyID那樣具體,它會減少查詢中的混淆 – kaj 2012-04-06 09:23:35

+0

老實說,我試圖避免短於5個字符的字段名。但我並不是創建數據庫的人。還有那個在2000年創建了數據庫的人。我正在做的工作是遷移到一個新的系統(由我設計一個全新的數據庫)。感謝您的建議。我會記住它。 – 2012-04-06 09:29:09

0
  1. 建設上郵編指數和住址

  2. 數據庫可能執行子查詢的每一行。 (在這裏只是猜測,在解釋計劃中非常有用,如果是這種情況,你可以重寫查詢以加入內聯視圖(注意這是它在oracle中的外觀,它也適用於sql server):

    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,Level 16,State 1,Line 6 '列'USERS.COMPANYID'在選擇列表中無效,因爲它沒有包含在集合函數或GROUP BY子句中。' – 2012-04-06 09:08:21

+0

對不起,錯過了組。添加它。可能還包含一個或多個拼寫錯誤..沒有在數據庫中嘗試它 – 2012-04-06 17:19:25

+0

直到星期二我都無法測試它,但是我會看看它是否有效。我們兩個人都可以從中學習一點權利? – 2012-04-06 21:36:22