简体   繁体   English

使用子查询来优化SQL?

[英]Optimize SQL with sub queries to?

I have following two tables in the bottom of the post. 我在帖子底部有两个表格。 The siteUsers table have a type column that can be "Member" or "Owner". siteUsers表的类型列可以为“成员”或“所有者”。 I am looking for a SQL that shows how many members and owners each site has. 我正在寻找一个SQL,该SQL显示每个站点有多少成员和所有者。 I could do something like: 我可以做类似的事情:

select 
    sites.Url,
    (select count(*) from siteusers where type='member' and siteusers.siteid=sites.siteid) as members,
    (select count(*) from siteusers where type='owners' and siteusers.siteid=sites.siteid) as owners
    from sites
    group by sites.url

However this is extreemly slow. 但是,这非常缓慢。 Is there a faster and smarter way? 有没有更快更聪明的方法?

Sites table: 网站表:

SiteId  int Unchecked
SPOSiteId   uniqueidentifier    Checked
Url nvarchar(MAX)   Checked

SiteUsers Table: SiteUsers表:

SiteUserId  int Unchecked
Type    nvarchar(256)   Checked
Name    nvarchar(512)   Checked
Email   nvarchar(512)   Checked
Host    nvarchar(256)   Checked
SiteId  int Checked

One way is: 一种方法是:

select s.Url,
       sum(case when su.type = 'member' then 1 else 0 end) as members,
       sum(case when su.type = 'owners' then 1 else 0 end) as owners,
from sites s left join
     siteusers su
     on s.siteid = su.siteid
where su.type in ('member', 'owners')
group by s.url;

You can do conditional aggregation with JOIN : 您可以使用JOIN进行条件聚合:

SELECT s.Url,
       SUM(CASE WHEN su.type ='member' THEN 1 ELSE 0 END) as members,
       SUM(CASE WHEN su.type ='owners' THEN 1 ELSE 0 END) as owners
FROM sites s INNER JOIN
     siteuser su
     ON su.siteid = s.siteid
GROUP BY s.Url;

However, you want index on sites(Url), siteuser(type) for better performance. 但是,您希望在sites(Url), siteuser(type)建立索引以获得更好的性能。

If the url is unique in sites , then this should be fast with the right indexes: 如果url是唯一sites ,那么这应该是快与正确的索引:

select s.Url,
    (select count(*) from siteusers su where su.type = 'member' and su.siteid = s.siteid) as members,
    (select count(*) from siteusers su where su.type = 'owners' and su.siteid = s.siteid) as owners
from sites s;

The right index is on siteusers(siteid, type) . 正确的索引位于siteusers(siteid, type) Of course, this assumes that url is unique which may not be the case. 当然,这假定url是唯一的,而事实并非如此。

Use Group By 使用分组依据

 select s.Url,su.type, count(*)

 from sites s join
 siteusers su
 on s.siteid = su.siteid

 group by s.url,su.type

I'd first check that proper primary keys and indexes are built: 我首先要检查是否构建了正确的主键和索引:

  • table Sites should have primary key SiteId Sites应具有主键SiteId
  • table SiteUsers should have primary key SiteUserId SiteUsers应该具有主键SiteUserId
  • table SiteUsers should have index on SiteId, type SiteUsers应该在SiteId, type上具有索引SiteId, type

then you can run following query to get results: 然后您可以运行以下查询以获取结果:

select s.url, t.members, t.owners
from Sites s inner join
(
  select
    SiteId, 
    sum(case when Type = 'member' then 1 else 0 end) as members,
    sum(case when Type = 'owners' then 1 else 0 end) as owners
  from SiteUsers
  group by SiteId
) t on s.SiteId = t.SiteId

this way you avoid group by varchar column 这样您可以避免group by varchar列group by

sample fiddle http://sqlfiddle.com/#!18/0b9b7/4 样本提琴http://sqlfiddle.com/#!18/0b9b7/4

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM