2014-12-03 83 views
0

我有2个表,COMPANYEMPLOYEE带查询SQL查询性能

COMPANY_IDCOMPANY表的主键和EMPLOYEE表的外键。 COMPANY_ID是一个10位数的数字。我们生成一个3位数组合并查询数据库。

select声明具有正则表达式来根据COMPANY_ID批量加载公司。该查询不同的图案执行多次

regexp_like(COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)') . 

现有的查询看起来是这样的 -

select * 
from COMPANY company 
where regexp_like(company.COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)') 

的新要求,是与员工计数一起获取公司信息。例如,如果一个公司有员工10人,则该查询应该返回COMPANY表中的所有列,与员工一起算即10

这是我想出了select语句 -

select 
    nvl(count_table.cont_count, 0), company.* 
from 
    COMPANY company, 
    (select company.COMPANY_ID, count(company.COMPANY_ID) as cont_count 
    from COMPANY company, EMPLOYEE employee 
    where regexp_like(company.COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)') 
     and company.CONTACT_ID = employee.CONTACT_ID  
    group by (company.COMPANY_ID)) count_table 
where 
    regexp_like(company.COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)') 
    and count_table.COMPANY_ID(+)= company.COMPANY_ID 

上面的查询工作,但它比以前的语句花费两倍的时间。有没有更好的方法来检索员工数量?

注意:Oracle数据库正在使用中。

+0

我不明白问题 – Strawberry 2014-12-03 17:57:42

+0

所以如果这是一个Oracle平台,为什么要列出Mysql和sql-server标签?您需要运行解释计划并查看数据库在查询中所做的事情。 – OldProgrammer 2014-12-03 17:58:15

+0

[踢坏的习惯:使用旧式JOIN](http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08/bad-habits-to-kick-using-old-style-joins。 aspx) - 在ANSI - ** 92 ** SQL标准(**超过20年前的**)中,旧式*逗号分隔的表*样式列表被替换为* proper * ANSI'JOIN'语法并且不鼓励使用它 – 2014-12-03 19:41:52

回答

2

你并不需要执行两次昂贵的REGEXP_LIKE:

select nvl(count_table.cont_count,0),company.* 
from COMPANY company 
,(select employee.COMPANY_ID, count(employee.COMPANY_ID) as cont_count 
    from  EMPLOYEE employee 
    group by (employee.COMPANY_ID) 
) count_table 
    where regexp_like(company.COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)') 
    and count_table.COMPANY_ID(+)= company.COMPANY_ID 

或者你可以使用标量子查询:

select company.* 
,  (select count(*) 
     from employee e 
     where e.company_id = c.company_id 
     ) 
from COMPANY c 
where regexp_like(c.COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)') 

而且我个人沟慢REGEXP_LIKE类似:

where substr(c.company_id,1,3) between '000' and '009' 
+0

是的,我喜欢substr的方法来表现。 – 2014-12-03 18:33:54

1

派生表不增加值,因此我会摆脱它,并使用标量查询(因为我不知道所有的运营商表列进行适当做一组由):

select c.*, 
    nvl(
    (select count(1) 
    from employee emp 
    where emp.company_id = c.company_id 
),0) employee_count 
from company c 
where regexp_like(c.company_id, '^(000|001|002|003|004|005|006|007|008|009)') 

此外,如果性能仍然是一个问题,我会考虑修改您的WHERE语句不使用一个正则表达式。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 附录 ~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~

我看到这个问题明确指出员工表有company_id作为外键。由于这是澄清,我删除此声明:

的数据模型为这些表是不直观(你会不会有 COMPANY_ID作为员工表的外键?)。