Counting groupwise category in SQL - sql

I want to find a category wise count in sql server with multiple criteria
Below is the table
I want to find groupwise, checklistcode wise status count
for instance group CLT having total count for Open status and Closed status
so output should look like this
CLT | Clinker transport | CL07M1 | Mechanical Requirments | 4 | 1
I have tried query which is as follows,
select distinct pd.GroupCode,
pd.GroupName,
pd.CheckListCode,
pd.CheckListName,
OpenTotal =
CASE WHEN pd.Status = 'Open' THEN COUNT(pd.Status)
END,
ClosedTotal =
CASE WHEN pd.Status = 'Closed' THEN COUNT(pd.Status)
END
from PunchListDetails pd
group by pd.GroupCode,
pd.GroupName,
pd.CheckListCode,
pd.CheckListName,
pd.Status;
But results is not according to my needs. This above query is showing following result
This is showing in two different lines but i want it in aggregated form as explained above.

Your approach is correct, but you are (also) grouping by the status, so you'll get a different row for each status - hence you get one row that counts the open statuses and one that counts the closed ones.
Just remove pd.Status from the end of the group by clause and you should be fine:
select distinct pd.GroupCode,pd.GroupName,pd.CheckListCode,pd.CheckListName,
OpenTotal =
CASE WHEN pd.Status = 'Open' THEN COUNT(pd.Status)
END,
ClosedTotal =
CASE WHEN pd.Status = 'Closed' THEN COUNT(pd.Status)
END
from PunchListDetails pd
group by pd.GroupCode,pd.GroupName,pd.CheckListCode,pd.CheckListName

You can try this:
SELECT GroupCode
,GroupName
,CheckListCode
,CheckListName,
,SUM(CASE WHEN Status = 'Open' THEN 1 ELSE 0 END) as OpenTotal
,SUM(CASE WHEN Status = 'Closed' THEN 1 ELSE 0 END) as ClosedTotal
FROM PunchListDetails
GROUP BY GroupCode,GroupName,CheckListCode,CheckListName

Related

Deriving values based on result of the query and grouping the data

I am writing a sql where I am trying to pull out information of the status of the courses the user has enrolled. I am trying to return single record for each user. Two fields in the select list would derive the value in the following manner
CourseResultStatusId -
If the status of all the courses is passed then return the status as passed otherwise.
If any status is fail, the overall status is fail.
If any of the status is expired, then overall status is expired.
If any of the status is in-progress then overall status is in-progress
ExpiryDateTime - Training expiring (nearest date)
I need to apply the following logic on courses he has been assigned.
cr.ExpiryDateTime > GetDate() and cr.ExpiryDateTime <= dateadd(dd,30,getdate()) )
If you see below , the query I have written so far pulls the courses that each user has been enrolled but it is not a cumulative result. Do I need to group, if yes would need help.
DECLARE #Rep1 INT;
SET #Rep1 = 13119;
SELECT
cr.[CourseID]
,cr.[UserID]
,u.[Code]
,u.[DisplayName]
,t.[Name]
,cr.[CourseResultStatusID] AS [CourseResultStatusID]
,crs.[Description] AS [CourseResultStatusDescription]
,c.[PointsRequired]
,cr.[ExpiryDateTime]
FROM [training].[CourseResult] cr
INNER JOIN [training].[Course] c
ON cr.[CourseID] = c.[ID] and c.[IsOptional] = 0 -- and cr.ExpiryDateTime > GetDate() and cr.ExpiryDateTime <= dateadd(dd,30,getdate())
INNER JOIN [training].[CourseResultStatus] crs
ON cr.[CourseResultStatusID] = crs.[ID]
INNER JOIN org.RepresentativeTierHistory rth on rth.RepresentativeID = cr.[UserID] and GetDate() between rth.StartDate and rth.EndDate
INNER JOIN org.tier t on t.ID = rth.TierID
LEFT JOIN [org].[User] u
ON u.[ID] = cr.[UserID]
WHERE cr.[UserID] IN (
SELECT hd.DescendantId FROM org.HierarchyDescendant hd WHERE hd.RepresentativeId = #Rep1 UNION ALL SELECT #Rep1 -- for management exchange info
)
order by UserID
The result of the query is as follows. I have circled to show you records that belong to a particular user and the columns that I am interested in . I need help in getting single record for each user based on the of logic that I mentioned above.
If I followed you correctly, you can implement the priorization rules on the overall result of each user using conditional aggregation.
Starting from your existing query, the logic would be:
select
cr.[UserID],
case
when min(case when crs.[Description] = 'Complete' then 1 else 0 end) = 1
then 'Complete'
when max(case when crs.[Description] = 'Fail' then 1 else 0 end) = 1
then 'Fail'
when max(case when crs.[Description] = 'Expired' then 1 else 0 end) = 1
then 'Expired'
when max(case when crs.[Description] = 'In Progress' then 1 else 0 end) = 1
then 'In Progress'
end as ResultStatus
from ...
where ...
group by cr.[UserID]
As for the date filtering logic, you should be able to implement it directly in the where clause.
It is possible that other parts of your query can be optimized - you might want to ask a new question for this, providing proper sample data and desired results.

Get table rows by multiple/end column value status

I have a table with example data like below:
InquiryId status
-------------------
inquiry1 New
inquiry1 Started
inquiry1 Done
inquiry2 New
inquiry2 Pending
inquiry3 New
inquiry3 Started
inquiry4 New
inquiry4 Cancelled
..and so on
Each inquiry starts with status as New and can reach either of the end status'es (Done, Cancelled..) via the middle status'es (Started, Pending..)
The question is how do find the list of inquiries that started with New but never reached the end status, i.e. what SQL query needs to be written to get the list of uncompleted inquiries.
P.S: Using Sybase Database
You can user the following query:
select distinct InquiryId
from <table_name>
where status not in('Done','Cancelled');
It will return all all the InquiryId which doesn't have the status as Done or Cancelled and is still in intermediate state.
You can use not exists :
select t.*
from table t
where status = 'New' and
not exists (select 1
from table t1
where t1.InquiryId = t.InquiryId and
t1.status in ('Done', 'Cancelled')
);
I would use aggregation:
select inquiryId
from t
group by inquiryId
having sum(case when status = 'New' then 1 else 0 end) > 0 and
sum(case when status in ('Done', 'Cancelled') then 1 else 0 end) = 0;
The conditions in the having clause count the number of rows for each inquiryId that meet the given conditions. The > 0 says that the inquiryId has at least one row. The = 0 says that the inquiryId has more than one row.

Report Builder 3.0 Count Parameter issue

new to SSRS,
Would have done the count in the SQL view, but issue I have is that I have a count, the count will have to be done in the Report Builder dataset. This is because I wish for users to change Start and End date parameters
I have a parameter count (filter) as 0 (this is the default), 1, 2, 3 ect when the report is run
I have the following as part of a data set
sum(case when Delivery_Code = 3 then 1
when Customer_id <> Customer_id then 1 else 0
end) as Count
the count is working
however I wish to say bring me back all customers first so >=0, (0 is the default value when report is first run) but when a users selects count of e.g 2 it filters to those
I have the following, but its not working
Having (sum(case when Delivery_Code = 3 then 1
when Customer_id <> Customer_id then 1 else 0
end) in (#Count) or (#Count) >= '0' )
please help
Just use = instead IN clause, since you have variable #Count which has only one single value
So,
Having (sum(case when Delivery_Code = 3
then 1
when Customer_id <> Customer_id
then 1 else 0
end) ) = #Count;

How to group and get count of rows based on value of one column in sql server

I have a table of requests with columns RequestType,status .Status column values can be in-progress,complated etc.
I would like to get the list like
RequestType In-Progress Completed Total
Type1 10 5 15
Type2 10 10 20
I tried with group by using the 2 columns( RequestType,status) ,but it does not give me the exact result.
Please help me with the sql query.
Thanks in advance
Subin
One way to do it is using conditional aggrigation:
SELECT RequestType,
SUM(CASE WHEN Status = 'In-Progress' THEN 1 ELSE 0 END) As 'In-Progress',
SUM(CASE WHEN Status = 'Completed' THEN 1 ELSE 0 END) As 'Completed',
COUNT(Status) As 'Total'
FROM TableName
WHERE Status IN('In-Progress', 'Completed')
GROUP BY RequestType
Use PIVOT
select *, [In-Progress]+[Completed] total
from TableName
pivot ( count(status) for status in ([In-Progress], [Completed])) as p

SQL Multiple Rows to Single Row Multiple Columns

I am including a SQLFiddle to show as an example of where I am currently at. In the example image you can see that simply grouping you get up to two lines per user depending on their status and how many of those statuses they have.
http://sqlfiddle.com/#!3/9aa649/2
The way I want it to come out is to look like the image below. Having a single line per user with two totaling columns one for Fail Total and one for Pass Total. I have been able to come close but since BOB only has Fails and not Passes this query leaves BOB out of the results. which I want to show BOB as well with his 6 Fail and 0 Pass
select a.PersonID,a.Name,a.Totals as FailTotal,b.Totals as PassTotals from (
select PersonID,Name,Status, COUNT(*) as Totals from UserReport
where Status = 'Fail'
group by PersonID,Name,Status) a
join
(
select PersonID,Name,Status, COUNT(*) as Totals from UserReport
where Status = 'Pass'
group by PersonID,Name,Status) b
on a.PersonID=b.PersonID
The below picture is what I want it to look like. Here is another SQL Fiddle that shows the above query in action
http://sqlfiddle.com/#!3/9aa649/13
Use conditional aggregation if the number of values for status column is fixed.
Fiddle
select PersonID,Name,
sum(case when "status" = 'Fail' then 1 else 0 end) as failedtotal,
sum(case when "status" = 'Pass' then 1 else 0 end) as passedtotals
from UserReport
group by PersonID,Name
Use conditional aggregation:
select PersonID, Name,
sum(case when Status = 'Fail' then 1 else 0 end) as FailedTotal,
sum(case when Status = 'Pass' then 1 else 0 end) as PassedTotal
from UserReport
group by PersonID, Name;
With conditional aggregation:
select PersonID,
Name,
sum(case when Status = 'Fail' then 1 end) as Failed,
sum(case when Status = 'Passed' then 1 end) as Passed
from UserReport
group by PersonID, Name