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