Need help Grouping and creating a select statement in Microsoft SQL Server - sql

I have 3 tables with these structures:
And the result that I am looking for is this:
I have tried multiple grouping statements but I have not been able to get near to something to the structure I need, if anybody can give me hand. Thanks

Here is one method:
select u.userid, u.name,
count(distinct case when b.visibility = 1 then b.blogid end) as num_public_blogs,
count(distinct case when b.visibility = 0 then b.blogid end) as num_private_blogs,
count(case when b.visibility = 1 then bp.blogid end) as num_public_posts,
count(case when b.visibility = 0 then bp.blogid end) as num_private_posts
from users u left join
blogs b
on b.userid = u.userid left join
blogposts bp
on bp.blogid = b.blogid
group by u.userid, u.name;

Related

Return multiple counts in a group by query

I have a 2 tables. A user table and a preference table.
Users
-UserId
Preferences
-PreferenceId
-UserId
-PreferenceType
-Enabled
I have a query to get be the number of users grouped by location:
SELECT u.Location, u.Count
FROM Users u
GROUP BY u.Location
I want to make a report of the Users by Location, but also include columns for each PreferenceType (say there are 3 types 'pref1', 'pref2', 'pref3'
So currently I am making a seperate query like this for each PreferenceType:
SELECT u.Location, u.Count
From Users u
inner join Preferences p ON p.UserId = u.UserId
WHERE
p.PreferenceType = 'pref1'
and p.Enabled = 1
GROUP BY u.Location
Would it be possible to combine all of these and get a result set like:
SELECT u.Location, u.Count, Pref1Count, Pref2Count, Pref3Count
From Users u
inner join Preferences p ON p.UserId = u.UserId
WHERE
You can use conditional aggregation:
select u.Location, count(distinct u.Userid) as cnt,
sum(case when p.PreferenceType = 'pref1' and p.Enabled = 1 then 1 else 0 end) as pref1,
sum(case when p.PreferenceType = 'pref2' and p.Enabled = 1 then 1 else 0 end) as pref2,
sum(case when p.PreferenceType = 'pref3' and p.Enabled = 1 then 1 else 0 end) as pref3,
From Users u left join
Preferences p
on p.UserId = u.UserId
group by u.Location;

Group by with case when

I have Projects - Issues, one to many relationship.
I want Pending issues and Completed issues for each project.
So, what I have done
SELECT
a.id ,
a.Name,
SUM(CASE WHEN b.StatusId = 3 THEN 1 ELSE NULL END) AS CompletedIssues,
SUM(CASE WHEN b.StatusId != 3 THEN 1 ELSE NULL END) AS PendingIssues
FROM
Projects a
JOIN Issues b
ON a.ID = b.ProjectId
GROUP BY
a.name,
b.StatusId,
a.ID
But it's not giving proper output. see below snap.
There are two separate rows for Completed and pending issues and sometimes more then 2 rows based upon Issues Status ID (See BT5).
Is case when is wrong for this scenario?
what is the proper way to achieve this?
Fix your group by:
select p.id, p.Name,
sum(case when i.StatusId = 3 then 1 else null end) as CompletedIssues,
sum(case when i.StatusId <> 3 then 1 else null end) as PendingIssues
from Projects p join
Issues i
on p.ID = i.ProjectId
group by p.name, p.id;
Note: You may not want else NULL. Normally, you want counts to be zero rather than NULL:
select p.id, p.Name,
sum(case when i.StatusId = 3 then 1 else 0 end) as CompletedIssues,
sum(case when i.StatusId <> 3 then 1 else 0 end) as PendingIssues
from Projects p join
Issues i
on p.ID = i.ProjectId
group by p.name, p.id;
Also, I changed the table aliases to something more meaningful. Don't use meaningless letters such as a and b. Use table abbreviations.

How to write queries where there are more than 2 conditions to extract info in postgresql?

I have tables as below
guides users offers reservations manager_crm_issues
id id id offer_id issuable_id
user_id username guide_id issuable_type issuable_type
What I Would like to extract is
guide.id,
guide.username,
manager_crm_issues.count(issuuable_id)
The issuable_type's distinct values are {Reservation, Offer, Guide}, and it corresponds to issuable_id.
i.e. if issuable_type = 'Reservation' then the issuable_id = reservation.id
Question is, I Would like to count all the issues happened on Guide, and Guide is linked to Offer, Offer is linked to Reservation.
SELECT
a.guideId,
a.guideName,
count(case when cr.issuable_type = 'Reservation' and cr.issuable_id = a.rID THEN cr.id else 0 END),
count(case when co.issuable_type = 'Offer' AND co.issuable_id = a.offerId THEN co.id else 0 END),
count(case when cg.issuable_type = 'Guide' AND cg.issuable_id = a.guideId THEN cg.id else 0 END)
FROM
(SELECT
g.id AS guideId,
u.username AS guideName,
o.id as offerId,
r.id as rId
FROM guides g
INNER JOIN users u on u.id = g.user_id
INNER JOIN offers AS o on o.guide_id = g.id
INNER JOIN reservations AS r on r.offer_id = o.id) a
INNER JOIN manager_crm_issues cg ON cg.id = a.guideId
INNER JOIN manager_crm_issues co ON co.id = a.offerId
INNER JOIN manager_crm_issues cr ON cr.id = a.rId
group by 1,2
I tried to join tables like above, but the outcome seems inaccurate.
Would really appreciate your help.
Don't know if this is related to your issue because you do not say what the issue is but this does not do what you think it does:
count(case
when cr.issuable_type = 'Reservation' and cr.issuable_id = a.rID THEN cr.id
else 0
END),
count counts not nulls so your query will count everything. What you want is
count(case
when cr.issuable_type = 'Reservation' and cr.issuable_id = a.rID THEN cr.id
else null
END),

Same values being returned for multiple rows in sql but not all columns

i'm currently running the following query (see below.)
However when i do the same values is returned for multiple rows in totalusers, activeusers and suspendedusers.
However when it comes to total login the values are unique.
Is their a reason why this could be happening and is their a way to solve the problem. If it helps im using the tool sql workben with postgre sql driver.
Cheers
SELECT
company.companyStatus,
company.CompanyId,
company.companyName,
select
count(distinct UserID)
From Users
inner join company
on Users.CompanyID = Company.CompanyId
where Users.Companyid = company.Companyid
as TotalUsers,
select sum(case when userstatusid =2 then 1 else 0 end)
from users
inner join company
on users.companyid = company.companyid
where users.companyid = company.companyid)
as ActiveUsers,
select sum(case when userstatusid = 3 then 1 else 0 end)
from users
inner join company
on users.companyid = company.companyid
where users.companyid = company.companyid)
as SuspendedUsers,
(Select COUNT (distinct usersessionid)
From UserSession
inner join users
on usersession.UserID=users.UserID
where usersession.UserID=users.UserID
and users.companyid= company.CompanyID)
as TotalLogin,
from Company
Its because your TotalUsers, ActiveUsers and SuspendedUsers queries are all using their own (unrestricted) copy of the Company table, whereas your TotalLogin is using the main instance from which you're selecting. This means that the TotalLogin numbers you're seeing are for that particular company, but the other fields are across ALL companies.
Presumably you wanted something more like:
SELECT
company.companyStatus,
company.CompanyId,
company.companyName,
count(distinct u.UserID) TotalUsers,
sum(case when u.userstatusid =2 then 1 else 0 end) ActiveUsers,
sum(case when u.userstatusid = 3 then 1 else 0 end) SuspendedUsers,
count(distinct u.usersessionid) TotalLogin
from Company
inner join Users on Users.CompanyID = Company.CompanyId
The reason is because you have company in the subqueries for those calculations.
I much prefer having table references in the from clause where possible, and you can write this query moving everything to the from clause:
SELECT c.companyStatus, c.CompanyId, c.companyName,
uc.Totalusers, uc.Activeusers, uc.Suspendedusers, ucs.TotalLogin
from Company c left outer join
(select u.companyid,
COUNT(distinct userid) as Totalusers,
SUM(case when userstatusid = 2 then 1 else 0 end) as ActiveUsers,
sum(case when userstatusid = 3 then 1 else 0 end) as Suspendedusers
from users u
group by u.companyid
) uc
uc.companyid = c.companyId left outer join
(select u.companyid, COUNT(distinct usersessionid) as TotalLogin
from UserSession us inner join
users u
on us.UserID = u.UserID
) ucs
on ucs.companyid = c.companyid;
This should also speed up the query because it doesn't have to do the same work multiple times.

Oracle SQL Sum missing right parenthesis

I have an Oracle SQL that works on MySQL, but I get the "missing right parenthesis" when I run On Oracle.
I put it on sqlfiddle
Oracle does not have a shorthand way of using a CASE or if like MySQL. As a result you will have to use a CASE inside of your sum:
select p.id, p.name,
t.id as toyid,
t.name as toyname
from person p
inner join toys t on p.id = t.person_id
inner join
(
select person_id
from toys
group by person_id
having sum(case when name = 'hat' then 1 else 0 end) > 0 and
sum(case when name = 'doll' then 1 else 0 end) > 0
) t2
on p.id = t2.person_id;
See SQL Fiddle with Demo