Reputation: 5225
I have following two tables in the bottom of the post. The siteUsers table have a type column that can be "Member" or "Owner". I am looking for a SQL that shows how many members and owners each site has. 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:
SiteUserId int Unchecked
Type nvarchar(256) Checked
Name nvarchar(512) Checked
Email nvarchar(512) Checked
Host nvarchar(256) Checked
SiteId int Checked
Upvotes: 0
Views: 62
Reputation: 50163
You can do conditional aggregation with 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.
If the url
is unique in sites
, then this should be fast with the right indexes:
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)
. Of course, this assumes that url
is unique which may not be the case.
Upvotes: 1
Reputation: 1269653
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;
Upvotes: 2
Reputation: 24146
I'd first check that proper primary keys and indexes are built:
Sites
should have primary key SiteId
SiteUsers
should have primary key SiteUserId
SiteUsers
should have index on 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
sample fiddle http://sqlfiddle.com/#!18/0b9b7/4
Upvotes: 1
Reputation: 885
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
Upvotes: 1