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

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.

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;

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

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;

How to get multiple counts in one sql query across multiple tables

I have 2 tables
Company & products
I need to get 2 counts. One is the total count of products and the secondly count of products for sale_flg=1
This SQL does not seem to work..Tried several other ways..not able to get the expected results
SELECT A.COMPANY_NAME, COUNT(B.PRODUCT_ID) AS TOTAL_COUNT_OF_PRODUCTS,
(CASE WHEN B.SALEFLG =1 THEN 1 END) AS COUNT_OF_SALES
FROM COMPANY A LEFT JOIN
PRODUCT B
ON B.COMPANY_ID = A.COMPANY_ID
GROUP BY A.COMPANY_NAME
I think you just need a sum for the case:
SELECT C.COMPANY_NAME, COUNT(P.PRODUCT_ID) AS TOTAL_COUNT_OF_PRODUCTS,
SUM(CASE WHEN P.SALEFLG = 1 THEN 1 ELSE 0 END) AS COUNT_OF_SALES
FROM COMPANY C LEFT JOIN
PRODUCT P
ON P.COMPANY_ID = C.COMPANY_ID
GROUP BY C.COMPANY_NAME ;
If you have B.SALEFLG = 1 or 0 for you may try
Sum(B.SALEFLG) AS COUNT_OF_SALES
Or use UNION
If you use count then in else you should consider null because null is not consider in count aggregation and if you have B.SALEFLG =1 or 0 then use sum aggregation.
You can try below code:
SELECT A.COMPANY_NAME, COUNT(B.PRODUCT_ID) AS TOTAL_COUNT_OF_PRODUCTS,
count(CASE WHEN B.SALEFLG =1 THEN 1 else null END) AS COUNT_OF_SALES
FROM COMPANY A LEFT JOIN
PRODUCT B
ON B.COMPANY_ID = A.COMPANY_ID
GROUP BY A.COMPANY_NAME
OR try this:
SELECT A.COMPANY_NAME, COUNT(B.PRODUCT_ID) AS TOTAL_COUNT_OF_PRODUCTS,
sum(B.SALEFLG) AS COUNT_OF_SALES
FROM COMPANY A LEFT JOIN
PRODUCT B
ON B.COMPANY_ID = A.COMPANY_ID
GROUP BY A.COMPANY_NAME
This SQL server query is working.
Company Table and Product Table
Company Table CompanyID is join with Product table and sales_flg add in product table .
sales_flg = 1 record display in CntSalesflg
select Comp.CompID as CompID, COUNT(Pro.ProductID) as CntProdustID,
SUM(CASE WHEN Pro.SalesflagID = 1 THEN 1 ELSE 0 END) as CntSalesflg
from Product as Pro
inner join Company as Comp on Pro.CompID = Comp.CompID
GROUP by Comp.CompID

COUNT Multiple tables with relationships and users

I've got a group of tables in SQL Server that I need to count on with specific counting criteria for each table, the problem I'm having that I need to group this by users, which are contained in one table and are mapped to the tables I need to count on via a relationship table.
This is the relationship table
Relationship User Work Item
Analyst 1 IR1
Analyst 2 IR2
Analyst 2 IR3
Analyst 1 IR4
User 3 IR1
Analyst 1 SR2
Analyst 1 SR3
Analyst 2 SR4
This is the IR table (the SR table is identical)
ID Status
IR1 Active
IR2 Active
IR3 Closed
IR4 Active
This is the user table
User Name
1 Dave
2 Jim
3 Karl
What I need is a table like below counting only the active items
Name IR Count SR Count
Dave 2 2
Jim 1 1
All I seem to be able to do currently is count all of the users regardless of status, I think this may be due to the left joins. I basically had:
Select u.name,
count (ir),
count (sr) from user u
Inner join relationship r on r.user=u.user and r.relationship = 'Analyst'
Left Join IR on r.workitem=ir.id and ir.Status = 'Active'
Left Join SR on r.workitem=sr.id and sr.Status = 'Active'
Group by u.name
I have simplified the above as much as possible. This is the actual query:
SELECT
u.DisplayName as Analyst,
u.BaseManagedEntityId as AUsername,
COUNT(distinct i.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) AS 'Active Incidents',
COUNT(distinct sr.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Service Requests',
COUNT(distinct cr.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Change Requests',
COUNT(distinct ma.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Manual Activities'
FROM MTV_System$Domain$User u
INNER JOIN RelationshipView r ON r.TargetEntityId = u.BaseManagedEntityId AND r.RelationshipTypeId = '15E577A3-6BF9-6713-4EAC-BA5A5B7C4722' AND r.IsDeleted ='0'
LEFT JOIN MTV_System$WorkItem$Incident i ON r.SourceEntityId = i.BaseManagedEntityId AND (i.Status_785407A9_729D_3A74_A383_575DB0CD50ED != '2B8830B6-59F0-F574-9C2A-F4B4682F1681' AND i.Status_785407A9_729D_3A74_A383_575DB0CD50ED != 'BD0AE7C4-3315-2EB3-7933-82DFC482DBAF')
LEFT JOIN MTV_System$WorkItem$ServiceRequest sr ON r.SourceEntityId = SR.BaseManagedEntityId AND (sr.Status_6DBB4A46_48F2_4D89_CBF6_215182E99E0F = '72B55E17-1C7D-B34C-53AE-F61F8732E425' OR sr.Status_6DBB4A46_48F2_4D89_CBF6_215182E99E0F = '59393F48-D85F-FA6D-2EBE-DCFF395D7ED1' OR sr.Status_6DBB4A46_48F2_4D89_CBF6_215182E99E0F = '05306BF5-A6B9-B5AD-326B-BA4E9724BF37')
LEFT JOIN MTV_System$WorkItem$ChangeRequest cr on r.SourceEntityId = cr.BaseManagedEntityId AND (cr.Status_72C1BC70_443C_C96F_A624_A94F1C857138 = '6D6C64DD-07AC-AAF5-F812-6A7CCEB5154D' or cr.Status_72C1BC70_443C_C96F_A624_A94F1C857138 = 'DD6B0870-BCEA-1520-993D-9F1337E39D4D')
LEFT JOIN MTV_System$WorkItem$Activity$ManualActivity MA on r.SourceEntityId = ma.BaseManagedEntityId AND (ma.Status_8895EC8D_2CBF_0D9D_E8EC_524DEFA00014 = '11FC3CEF-15E5-BCA4-DEE0-9C1155EC8D83' OR ma.Status_8895EC8D_2CBF_0D9D_E8EC_524DEFA00014 = 'D544258F-24DA-1CF3-C230-B057AAA66BED')
GROUP BY u.DisplayName,u.BaseManagedEntityId
Order by u.DisplayName
your over simplification seems to have lost your what appears to be your issue from some of your comments. Using left joins would include any of the users even if they don't have a count of one of your other tables. However if you want your result set to only include usres that have at least 1 Incident and/or 1 Request and/or 1 Change Request. Etc. you can either filter the aggretation you are doing after the fact to remove when Incidents + Requests + ... = 0. Or you can filter them out by adding a WHERE statement that says WHEN NOT all of those other tables are null which is the same as OR IS NOT NULL...
SELECT
u.DisplayName as Analyst,
u.BaseManagedEntityId as AUsername,
COUNT(distinct i.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) AS 'Active Incidents',
COUNT(distinct sr.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Service Requests',
COUNT(distinct cr.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Change Requests',
COUNT(distinct ma.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Manual Activities'
FROM
MTV_System$Domain$User u
INNER JOIN RelationshipView r
ON r.TargetEntityId = u.BaseManagedEntityId
AND r.RelationshipTypeId = '15E577A3-6BF9-6713-4EAC-BA5A5B7C4722'
AND r.IsDeleted ='0'
LEFT JOIN MTV_System$WorkItem$Incident i
ON r.SourceEntityId = i.BaseManagedEntityId
AND i.Status_785407A9_729D_3A74_A383_575DB0CD50ED NOT IN ('2B8830B6-59F0-F574-9C2A-F4B4682F1681','BD0AE7C4-3315-2EB3-7933-82DFC482DBAF')
LEFT JOIN MTV_System$WorkItem$ServiceRequest sr
ON r.SourceEntityId = SR.BaseManagedEntityId
AND sr.Status_6DBB4A46_48F2_4D89_CBF6_215182E99E0F IN ('72B55E17-1C7D-B34C-53AE-F61F8732E425','59393F48-D85F-FA6D-2EBE-DCFF395D7ED1','05306BF5-A6B9-B5AD-326B-BA4E9724BF37')
LEFT JOIN MTV_System$WorkItem$ChangeRequest cr
ON r.SourceEntityId = cr.BaseManagedEntityId
AND cr.Status_72C1BC70_443C_C96F_A624_A94F1C857138 IN ('6D6C64DD-07AC-AAF5-F812-6A7CCEB5154D','DD6B0870-BCEA-1520-993D-9F1337E39D4D')
LEFT JOIN MTV_System$WorkItem$Activity$ManualActivity MA
ON r.SourceEntityId = ma.BaseManagedEntityId
AND ma.Status_8895EC8D_2CBF_0D9D_E8EC_524DEFA00014 IN ('11FC3CEF-15E5-BCA4-DEE0-9C1155EC8D83','D544258F-24DA-1CF3-C230-B057AAA66BED')
WHERE
i.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C IS NOT NULL
OR sr.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C IS NOT NULL
OR cr.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C IS NOT NULL
OR ma.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C IS NOT NULL
GROUP BY u.DisplayName,u.BaseManagedEntityId
Order by u.DisplayName
Also note the user of IN and NOT IN in the join conditions instead of OR all of the time.
The issue is count(). Instead, you want count(distinct):
Select u.name,
count(distinct ir),
count(distinct sr)
from user u
. . .
This generates a Cartesian product between the ir and sr values. If you have largish numbers in each group, then aggregating before the join is a better approach.
;WITH T AS
(
SELECT
U.UserID,
U.Name,
CASE WHEN R.WorkItem LIKE 'IR%' THEN R.WorkItem ELSE '' END AS IRCode,
CASE WHEN R.WorkItem LIKE 'SR%' THEN R.WorkItem ELSE '' END AS SRCode
FROM #tblUser U
INNER JOIN #tblRelationship R ON U.UserId=R.UserId
)
SELECT
Name,
SUM(CASE IRCode WHEN '' THEN 0 ELSE 1 END) AS 'IR Count',
SUM(CASE SRCode WHEN '' THEN 0 ELSE 1 END) AS 'SR Count'
FROM T
WHERE
(
(T.IRCode=''
OR
T.SRCode='')
AND
(
T.IRCode IN (SELECT ID FROM #tblIR WHERE Status='Active')
OR
T.SRCode IN (SELECT ID FROM #tblSR WHERE Status='Active')
)
)
GROUP BY T.Name
Try with the below script .
SELECT u.name
,SUM(t1.[IR Count]) [IR Count]
,SUM(t2.[SR Count]) [SR Count]
FROM #user u
INNER JOIN #relationship r on r.[user]=u.[user]and r.relationship = 'Analyst'
CROSS APPLY (SELECT COUNT(DISTINCT ID) [IR Count]
FROM #IR ir WHERE r.workitem=ir.id and ir.Status = 'Active') t1
CROSS APPLY (SELECT COUNT(DISTINCT ID) [SR Count]
FROM #SR sr WHERE r.workitem=sr.id and sr.Status = 'Active')t2
GROUP BY u.name
OUTPUT :
SR Count in your sample output is wrong ,if the SR table is same as that of IR table (Status of the SR3 is closed for the user 'dave' so that will be ignored.) .
This is what I've come up with that seems to work based off the actual table
SELECT
u.DisplayName as Analyst,
u.BaseManagedEntityId as AUsername,
COUNT(distinct i.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) AS 'Active Incidents',
COUNT(distinct sr.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Service Requests',
COUNT(distinct cr.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Change Requests',
COUNT(distinct ma.Id_9A505725_E2F2_447F_271B_9B9F4F0D190C) as 'Active Manual Activities'
FROM MTV_System$Domain$User u
LEFT JOIN RelationshipView r ON r.TargetEntityId = u.BaseManagedEntityId AND r.RelationshipTypeId = '15E577A3-6BF9-6713-4EAC-BA5A5B7C4722' AND r.IsDeleted ='0'
LEFT JOIN MTV_System$WorkItem$Incident i ON r.SourceEntityId = i.BaseManagedEntityId
LEFT JOIN MTV_System$WorkItem$ServiceRequest sr ON r.SourceEntityId = SR.BaseManagedEntityId
LEFT JOIN MTV_System$WorkItem$ChangeRequest cr on r.SourceEntityId = cr.BaseManagedEntityId
LEFT JOIN MTV_System$WorkItem$Activity$ManualActivity MA on r.SourceEntityId = ma.BaseManagedEntityId
Where (i.Status_785407A9_729D_3A74_A383_575DB0CD50ED != '2B8830B6-59F0-F574-9C2A-F4B4682F1681' AND i.Status_785407A9_729D_3A74_A383_575DB0CD50ED != 'BD0AE7C4-3315-2EB3-7933-82DFC482DBAF')
OR (sr.Status_6DBB4A46_48F2_4D89_CBF6_215182E99E0F = '72B55E17-1C7D-B34C-53AE-F61F8732E425' OR sr.Status_6DBB4A46_48F2_4D89_CBF6_215182E99E0F = '59393F48-D85F-FA6D-2EBE-DCFF395D7ED1' OR sr.Status_6DBB4A46_48F2_4D89_CBF6_215182E99E0F = '05306BF5-A6B9-B5AD-326B-BA4E9724BF37')
OR (cr.Status_72C1BC70_443C_C96F_A624_A94F1C857138 = '6D6C64DD-07AC-AAF5-F812-6A7CCEB5154D' or cr.Status_72C1BC70_443C_C96F_A624_A94F1C857138 = 'DD6B0870-BCEA-1520-993D-9F1337E39D4D')
OR (ma.Status_8895EC8D_2CBF_0D9D_E8EC_524DEFA00014 = '11FC3CEF-15E5-BCA4-DEE0-9C1155EC8D83' OR ma.Status_8895EC8D_2CBF_0D9D_E8EC_524DEFA00014 = 'D544258F-24DA-1CF3-C230-B057AAA66BED')
GROUP BY u.DisplayName,u.BaseManagedEntityId
Order by u.DisplayName

Sub sum query bringing back more results then possible

I am currently running the following query.( See below) However when I run this query the active users and Suspended users are bring back a far greater result then that's in the database.
I just wondered if you could possibly shed light on the reason why and correct me where I'm going wrong?
SELECT c.[Status],
c.CompanyId,
c.Name,
(SELECT count(DISTINCT usr.UserID)
FROM [ondemand.10cms.com].Security.[user] usr
INNER JOIN [ondemand.10cms.com].Company.Company
ON usr.CompanyID = c.CompanyID) AS TotalUsers,
(SELECT sum (CASE
WHEN usr.Status = 2 THEN 1
ELSE 0
END)
FROM [ondemand.10cms.com].Security.[user] usr
INNER JOIN [ondemand.10cms.com].Company.Company
ON usr.CompanyID = c.CompanyID) AS ActiveUsers,
(SELECT sum (CASE
WHEN usr.Status = 3 THEN 1
ELSE 0
END)
FROM [ondemand.10cms.com].Security.[User] usr
INNER JOIN [ondemand.10cms.com].Company.Company
ON usr.CompanyID = c.CompanyID) AS SuspendedUsers
FROM [ondemand.10cms.com].Company.Company c
In each of your sub queries you have two tables, one is being joined to the outer query but there is no join between the two inner tables. All of those sub queries are a bit unnecessary, I would rewrite as a simpler query, something like so:
SELECT
Company.[Status]
,Company.CompanyId
,Company.Name
,COUNT(DISTINCT usr.UserID) AS TotalUsers
,SUM(CASE WHEN usr.Status = 2 THEN 1
ELSE 0
END) AS ActiveUsers
,SUM(CASE WHEN usr.Status = 3 THEN 1
ELSE 0
END) AS SuspendedUsers
FROM [ondemand.10cms.com].Security.[user] usr
INNER JOIN [ondemand.10cms.com].Company.Company
ON usr.CompanyID = Company.CompanyID
GROUP BY
Company.[Status]
,Company.CompanyId
,Company.Name
If you just wabt a fix for your query as is then try this:
SELECT c.[Status],
c.CompanyId,
c.Name,
(SELECT count(DISTINCT usr.UserID)
FROM [ondemand.10cms.com].Security.[user] usr
INNER JOIN [ondemand.10cms.com].Company.Company
ON usr.CompanyID = Company.CompanyID
WHERE usr.CompanyID = c.CompanyID) AS TotalUsers,
(SELECT sum (CASE
WHEN usr.Status = 2 THEN 1
ELSE 0
END)
FROM [ondemand.10cms.com].Security.[user] usr
INNER JOIN [ondemand.10cms.com].Company.Company
ON usr.CompanyID = Company.CompanyID
WHERE usr.CompanyID = c.CompanyID) AS ActiveUsers,
(SELECT sum (CASE
WHEN usr.Status = 3 THEN 1
ELSE 0
END)
FROM [ondemand.10cms.com].Security.[User] usr
INNER JOIN [ondemand.10cms.com].Company.Company
ON usr.CompanyID = Company.CompanyID
WHERE usr.CompanyID = c.CompanyID) AS SuspendedUsers
FROM [ondemand.10cms.com].Company.Company c
I don't know your data (it could cause duplicates), but couldnt you use a standard group by and not use sub queries?
Select
c.[Status],
c.CompanyId,
c.Name,
count(distinct usr.UserID) as TotalUsers,
sum(case when usr.Status = 2 then 1 else 0 end) as ActiveUsers,
sum(case when usr.Status = 3 then 1 else 0 end) as SuspendedUsers
from [ondemand.10cms.com].Company.Company c
inner join [ondemand.10cms.com].Security.[user] usr
on usr.CompanyID=c.CompanyID
GROUP BY
c.[Status],
c.CompanyId,
c.Name
Try adding a group by CompanyId and let us know how that worked.