Formatting multiple SELECT statements with PIVOT - sql

Currently have a script that unions around a dozen SELECT statements, and example of two of these along with an example of the results is shown below.
DECLARE #Age TABLE (name VARCHAR(30), total FLOAT, percentage FLOAT)
INSERT INTO #Age
SELECT '0-18', (SELECT COUNT(*) FROM tblPerson p
INNER JOIN tblClient c ON c.intPersonID = p.intPersonID
WHERE ISNULL(dbo.fncReportClient_Age(p.dteBirthdate, GETDATE()), '') >= 0 AND ISNULL(dbo.fncReportClient_Age(p.dteBirthdate, GETDATE()), '') <= 18), ''
UPDATE #Age
SET percentage = ROUND((SELECT total FROM #Age WHERE name = '0-18')/(SELECT SUM(total) FROM #Age) * 100, 2)
FROM #Age
WHERE name = '0-18'
Etc.
SELECT
g.nvhGenderName,
COUNT(*),
ROUND(COUNT(*) * 1.0 / SUM(COUNT(*)) OVER () * 100, 2)
FROM
tblClient c
LEFT JOIN tblPerson p ON p.intPersonID = c.intPersonID
LEFT JOIN tblGender g ON g.intGenderID = p.intGenderID
GROUP BY g.nvhGenderName
UNION ALL
SELECT * FROM #Age
Results example below:
Name | Total | % |
---------------------------------
Male | 6514 | 60.32 |
Female | 4285 | 39.68 |
0-18 | 279 | 1.58 |
19-24 | 1748 | 9.93 |
25-34 | 5423 | 30.80 |
35-64 | 9546 | 54.21 |
65+ | 614 | 3.50 |
I would like to display these results horizontally as opposed to vertically, I think it is possible to do this with PIVOT but have never really used them. An example of how I want the data to be displayed is shown below:
Gender | Total | % | Age | Total | % |
-------------------------------------------------------------
Male | 6514 | 60.32 | 0-18 | 279 | 1.58 |
Female | 4285 | 39.68 | 19-24 | 1748 | 9.93 |
| | | 25-34 | 5423 | 30.80 |
| | | 35-64 | 9546 | 54.21 |
| | | 65+ | 614 | 3.50 |
In particular I am not sure how I would use a pivot to combine the multiple (12) SELECT statements that require it.
Any help on how to format this would be much appreciated.

Whilst I believe the layout really should be achieved elsewhere, the following may work for you. Clearly I cannot test it so, without the benefit of testing here goes:
WITH myCTE AS (
SELECT
COUNT(CASE WHEN oa.age >= 0 AND oa.age < 19 THEN p.intPersonID ELSE NULL END) c0019
, COUNT(CASE WHEN oa.age >= 19 AND oa.age < 25 THEN p.intPersonID ELSE NULL END) c1925
, COUNT(CASE WHEN oa.age >= 25 AND oa.age < 35 THEN p.intPersonID ELSE NULL END) c2535
, COUNT(CASE WHEN oa.age >= 35 AND oa.age < 65 THEN p.intPersonID ELSE NULL END) c3565
, COUNT(CASE WHEN oa.age >= 65 THEN p.intPersonID ELSE NULL END) c65on
, COUNT(CASE WHEN g.nvhGenderName = 'Male' THEN p.intPersonID ELSE NULL END) cmale
, COUNT(CASE WHEN g.nvhGenderName = 'Female' THEN p.intPersonID ELSE NULL END) cfemale
, COUNT(*) ctotal
FROM tblClient c
LEFT JOIN tblPerson p ON p.intPersonID = c.intPersonID
OUTER APPLY (
SELECT
dbo.fncReportClient_Age(p.dteBirthdate) AS age
) AS oa
LEFT JOIN tblGender g ON g.intGenderID = p.intGenderID
)
SELECT
ca.Gender, ca.Total2, ca.Pct, ca.Age, ca.Total2, ca.Pct2
FROM myCTE
CROSS APPLY (
VALUES
(1, 'Male' , t.cmale , (cmale * 100.0 / ctotal), '0-18', c0019, (c0019 * 100.0 / ctotal))
, (2, 'Female',t.cfemale,(cfemale * 100.0 / ctotal), '19-24', c1925, (c1925 * 100.0 / ctotal))
, (3, NULL,NULL,NULL, '25-34', c2535, (c2535 * 100.0 / ctotal))
, (4, NULL,NULL,NULL, '35-64', c3565, (c3565 * 100.0 / ctotal))
, (5, NULL,NULL,NULL, '65+' , c65on, (c65on * 100.0 / ctotal))
) AS ca (rn, Gender, Total2, Pct, Age, Total2, Pct2)
ORDER BY ca.rn
;
The second (lower) part of the query above uses a technique for unpivoting data that combines cross apply with values and this allows us to "layout" each row of the wanted final result row by row.
Using a CTE (the upper part of the query above) isn't essential, it could be moved into a subquery instead, but the query inside the CTE should be trialed standalone first and it should produce all the numbers you need in one pass of the data (assuming that the gender table doesn't disturb the count results). Note that using count(case expression here) removes the need for multiple separate queries. I suspect you don't need left joins by the way, and if that is true you could also change the outer apply to a cross apply. Note that the apply is used to execute your function, and by doing it ths way we are able to reference the result of that function by an alias in the remainder of the query (I used "age" as that alias).
I am unsure why you involve a client table when counting the persons table. I suspect it isn't needed. If my suspicions are correct the CTE detail could be replaced by this:
SELECT
COUNT(CASE WHEN oa.age >= 0 AND oa.age < 19 THEN 1 ELSE NULL END) c0019
, COUNT(CASE WHEN oa.age >= 19 AND oa.age < 25 THEN 1 ELSE NULL END) c1925
, COUNT(CASE WHEN oa.age >= 25 AND oa.age < 35 THEN 1 ELSE NULL END) c2535
, COUNT(CASE WHEN oa.age >= 35 AND oa.age < 65 THEN 1 ELSE NULL END) c3565
, COUNT(CASE WHEN oa.age >= 65 THEN 1 ELSE NULL END) c65on
, COUNT(CASE WHEN g.nvhGenderName = 'Male' THEN 1 ELSE NULL END) cmale
, COUNT(CASE WHEN g.nvhGenderName = 'Feale' THEN 1 ELSE NULL END) cfemale
, COUNT(*) ctotal
FROM tblPerson p
CROSS APPLY (
SELECT
dbo.fncReportClient_Age(p.dteBirthdate) AS age
) AS oa
INNER JOIN tblGender g ON g.intGenderID = p.intGenderID

Create VIEW view_name AS
SELECT * FROM (
select ColumnName1,ColumnName2 from TableName
) as s
PIVOT (
Sum(ColumnName2)
FOR ColumnName3 in ("Row1","Row2","Row3"
)
) As pvt
DROP VIEW view_name;
Select * from view_name

Related

Creating a new column for -ve values from the existing rows

How to write logic for this in SQL Server:
Voucher # Name Amount
-------------------------
123 ABC 910
123 ABC -910
224 XYZ 600
Expected output
Voucher # Name Amount - (Amount)
-------------------------------------------
123 ABC 910 -910
224 XYZ 600 -
Using conditional aggregation is really simple here. No need to query the same table over and over.
select Voucher
, Name
, Amount = sum(case when Amount > 0 then Amount else 0 end)
, [-Amount] = sum(case when Amount < 0 then Amount else 0 end)
from YourTable
group by Voucher
, Name
Here is the code, try it
Group by negative and positive amount and make a left join
DECLARE #tbl TABLE
(
Voucher varchar(10),
Name varchar(100),
Amount int
)
INSERT INTO #tbl
(
Voucher,
Name,
Amount
)
VALUES
(123,'ABC',910),
(123,'ABC',-910),
(224,'XYZ',600)
SELECT t1.Voucher, t1.Name, t1.Amount , ISNULL(t2.Amount,0) AS [(-Amount)] FROM (
SELECT t.Voucher, Name, Sum(t.Amount) Amount
FROM #tbl t
WHERE t.Amount > 0
GROUP BY t.Voucher, t.Name) t1 Left JOIN
(SELECT t.Voucher, Name, Sum(t.Amount) Amount
FROM #tbl t
WHERE t.Amount < 0
GROUP BY t.Voucher, t.Name) t2 ON t1.Voucher = t2.Voucher
If for each (Voucher, Name) there exists only 1 positive Amount and 0 or 1 negative Amount then with a self join:
select t.*, tt.amount NegativeAmount
from tablename t left join tablename tt
on tt.voucher = t.voucher and tt.name = t.name and tt.amount < 0
where t.amount > 0
See the demo.
Results:
> voucher | name | amount | NegativeAmount
> ------: | :--- | -----: | -------------:
> 123 | ABC | 910 | -910
> 224 | XYZ | 600 |

In T-SQL, What is the best way to find % of male customers by area

Support I have a table with area, customer and customer's sex info and I want to find out % of male customers in each area. Whats the best way to come up with that?
create table temp(area_id varchar(10),customer_id varchar(10),customer_sex varchar(10))
insert into temp select 1,1,'male'
insert into temp select 1,1,'male'
insert into temp select 1,1,'female'
insert into temp select 1,1,'female'
insert into temp select 2,1,'male'
insert into temp select 2,1,'female'
insert into temp select 2,1,'female'
insert into temp select 3,1,'male'
insert into temp select 3,1,'female'
insert into temp select 4,1,'male'
insert into temp select 5,1,'female'
select * from temp
The result should be like below:
; WITH x AS
(
select
area_id
, count(*) AS total_customers
, SUM(CASE WHEN customer_sex = 'male' THEN 1 ELSE 0 END) AS total_male_customers
FROM temp
GROUP BY area_id
)
SELECT
area_id
, total_customers
, total_male_customers
, CASE WHEN total_male_customers > 0 THEN CAST( (total_male_customers * 100.0) / total_customers AS DECIMAL(6,2)) ELSE 0 END AS Male_percentage
From x
Group by and case will provide your results:
SELECT area_id, count(customer_id) as Total_Customers, Total_Male_Customers = sum(case when customer_sex = 'male' then 1 else 0 end),
Format(sum(case when customer_sex = 'male' then 1 else 0 end)/(count(customer_id)*1.0),'P') as MaleCustomers
FROM dbo.temp
GROUP BY area_id
HAVING sum(case when customer_sex = 'male' then 1 else 0 end) > 0
Here if it is smaller dataset format is better else it has performance issues you can go with custom multiplication and concatenating % symbol.
Output as below:
+---------+-----------------+----------------------+---------------+
| area_id | Total_Customers | Total_Male_Customers | MaleCustomers |
+---------+-----------------+----------------------+---------------+
| 1 | 4 | 2 | 50.00 % |
| 2 | 3 | 1 | 33.33 % |
| 3 | 2 | 1 | 50.00 % |
| 4 | 1 | 1 | 100.00 % |
+---------+-----------------+----------------------+---------------+
Use IIF (Sqlserver 2012+) otherwise CASE, group by and sum of males /count all customers * 100
+ 0.0 to treat sum of males and all customer as float or decimal to get the correct result.
select area_id,count(customer_id) [Total Customers],
sum(iif(customer_sex='male',1,0)) [Total Males],
cast(cast(((sum(iif(customer_sex='male',1,0)) + 0.0) / (count(customer_sex) + 0.0)) * 100 as decimal(18,1)) as varchar(10)) + '%' [percentage of males]
from temp
group by area_id
This will do:
select x.area_id, x.total, x.m, cast(CONVERT(DECIMAL(10,2), x.m * 100.0 / x.total) as nvarchar(max)) + '%'
from
(
select t.area_id, count(1) total, sum(iif(t.customer_sex = 'male', 1, 0)) m
from #temp t
group by t.area_id
)x

SQL query sum of total corresponding rows

I have two tables as below. Caseid from first table is referenced in second table along with accidents. What I am trying to get total different accidents for a case type. Below two tables I documented sample data and expected result.
Table case:
caseId CaseType
1 AB
2 AB
3 AB
4 CD
5 CD
6 DE
Table CaseAccidents:
AccidentId caseID AccidentRating
1 1 High
2 1 High
3 1 Medium
4 1 LOW
5 2 High
6 2 Medium
7 2 LOW
8 5 High
9 5 High
10 5 Medium
11 5 LOW
Result should look like:
CaseType TotalHIghrating TotalMediumRating TotalLOWRating
AB 3 2 2
CD 2 1 1
DE 0 0 0
To get the sum of every rating, you can Use a SUM(CASE WHEN) clause, adding 1 by every record that match the rating.
In your question, you have pointed out that you want to see all distinct CaseType, you can get it by using a RIGHT JOIN, this will include all records of case table.
select case.CaseType,
sum(case when caseAccidents.AccidentRating = 'High' then 1 else 0 end) as TotalHighRating,
sum(case when caseAccidents.AccidentRating = 'Medium' then 1 else 0 end) as TotalMediumRating,
sum(case when caseAccidents.AccidentRating = 'LOW' then 1 else 0 end) as TotalLowRating
from caseAccidents
right join case on case.caseId = caseAccidents.caseID
group by case.CaseType;
+----------+-----------------+-------------------+----------------+
| CaseType | TotalHighRating | TotalMediumRating | TotalLowRating |
+----------+-----------------+-------------------+----------------+
| AB | 3 | 2 | 2 |
+----------+-----------------+-------------------+----------------+
| CD | 2 | 1 | 1 |
+----------+-----------------+-------------------+----------------+
| DE | 0 | 0 | 0 |
+----------+-----------------+-------------------+----------------+
Check it: http://rextester.com/MCGJA9193
Have you use case in a select clause before?
select C.CaseType,
sum(case when CA.AccidentRating = 'High' then 1 else 0 end)
from Case C join CaseAccidents CA on C.CaseId = CA.CaseId
group by C.CaseType
Please see this. Sample query of the table and also that result
create table #case(caseid int,casetype varchar(5))
insert into #case (caseid,casetype)
select 1,'AB' union all
select 2,'AB' union all
select 3,'AB' union all
select 4,'CD' union all
select 5,'CD' union all
select 6,'DE'
create table #CaseAccidents(AccidentId int, CaseId int,AccidentRating varchar(10))
insert into #CaseAccidents(AccidentId, CaseId, AccidentRating)
select 1,1,'High' union all
select 2,1,'High' union all
select 3,1,'Medium' union all
select 4,1,'Low' union all
select 5,2,'High' union all
select 6,2,'Medium' union all
select 7,2,'Low' union all
select 8,5,'High' union all
select 9,5,'High' union all
select 10,5,'Medium' union all
select 11,5,'Low'
My script
select c.casetype,
sum(case when ca.AccidentRating='High' then 1 else 0 end) as TotalHighRating,
sum(case when ca.AccidentRating='Medium' then 1 else 0 end) as TotalMediumRating,
sum(case when ca.AccidentRating='Low' then 1 else 0 end) as TotalLowRating
from #case c
Left join #CaseAccidents ca
on c.Caseid=ca.Caseid
group by c.casetype
Hope This could help!
Another approach using Pivot operator
SELECT casetype,
[High],
[Medium],
[Low]
FROM (SELECT c.casetype,
AccidentRating
FROM case c
LEFT JOIN CaseAccidents ca
ON ca.CaseId = c.caseid)a
PIVOT (Count(AccidentRating)
FOR AccidentRating IN ([High],
[Medium],
[Low]) ) p
Try This code once.
select casetype,
sum(case when ca.AccidentRating='High' then 1 else 0 end ) as TotalHIghrating,
sum(case when ca.AccidentRating='Medium' then 1 else 0 end ) as TotalMediumRating ,
sum(case when ca.AccidentRating='Low' then 1 else 0 end ) as TotalLOWRating
from #case c
left join #CaseAccidents ca on c.caseid=ca.CaseId
group by casetype

Aggregative sum of objects belonging to objects residing inside hierarchy structure

My problem is similar in a way to this one, yet different enough in my understanding.
I have three tables:
Units ([UnitID] int, [UnitParentID] int)
Students ([StudentID] int, [UnitID] int)
Events ([EventID] int, [EventTypeID] int, [StudentID] int)
Students belong to units, units are stacked in a hierarchy (tree form - one parent per child), and each student can have events of different types.
I need to sum up the number of events of each type per user, then aggregate for all users in a unit, then aggregate through hierarchy until I reach the mother of all units.
The result should be something like this:
My tools are SQL Server 2008 and Report Builder 3.
I put up a SQL fiddle with sample data for fun.
Use this query:
;WITH CTE(Id, ParentId, cLevel, Title, ord) AS (
SELECT
u.UnitID, u.UnitParentID, 1,
CAST('Unit ' + CAST(ROW_NUMBER() OVER (ORDER BY u.UnitID) AS varchar(3)) AS varchar(max)),
CAST(RIGHT('000' + CAST(ROW_NUMBER() OVER (ORDER BY u.UnitID) AS varchar(3)), 3) AS varchar(max))
FROM
dbo.Units u
WHERE
u.UnitParentID IS NULL
UNION ALL
SELECT
u.UnitID, u.UnitParentID, c.cLevel + 1,
c.Title + '.' + CAST(ROW_NUMBER() OVER (PARTITION BY c.cLevel ORDER BY c.Id) AS varchar(3)),
c.ord + RIGHT('000' + CAST(ROW_NUMBER() OVER (ORDER BY u.UnitID) AS varchar(3)), 3)
FROM
dbo.Units u
JOIN
CTE c ON c.Id = u.UnitParentID
WHERE
u.UnitParentID IS NOT NULL
), Units AS (
SELECT
u.Id, u.ParentId, u.cLevel, u.Title, u.ord,
SUM(CASE WHEN e.EventTypeId = 1 THEN 1 ELSE 0 END) AS EventA,
SUM(CASE WHEN e.EventTypeId = 2 THEN 1 ELSE 0 END) AS EventB,
SUM(CASE WHEN e.EventTypeId = 3 THEN 1 ELSE 0 END) AS EventC,
SUM(CASE WHEN e.EventTypeId = 4 THEN 1 ELSE 0 END) AS EventD
FROM
CTE u
LEFT JOIN
dbo.Students s ON u.Id = s.UnitId
LEFT JOIN
dbo.[Events] e ON s.StudentId = e.StudentId
GROUP BY
u.Id, u.ParentId, u.cLevel, u.Title, u.ord
), addStudents AS (
SELECT *
FROM Units
UNION ALL
SELECT
s.StudentId, u.Id, u.cLevel + 1,
'Student ' + CAST(s.StudentId AS varchar(3)),
u.ord + RIGHT('000' + CAST(s.StudentId AS varchar(3)), 0),
SUM(CASE WHEN e.EventTypeId = 1 THEN 1 ELSE 0 END),
SUM(CASE WHEN e.EventTypeId = 2 THEN 1 ELSE 0 END),
SUM(CASE WHEN e.EventTypeId = 3 THEN 1 ELSE 0 END),
SUM(CASE WHEN e.EventTypeId = 4 THEN 1 ELSE 0 END)
FROM Units u
JOIN
dbo.Students s ON u.Id = s.UnitId
LEFT JOIN
dbo.[Events] e ON s.StudentId = e.StudentId
GROUP BY
s.StudentID, u.ID, u.cLevel, u.ord
)
SELECT --TOP(10)
REPLICATE(' ', cLevel) + Title As Title,
EventA, EventB, EventC, EventD
FROM
addStudents
ORDER BY
ord
For this:
Title | EventA | EventB | EventC | EventD
-----------------+--------+---------+--------+--------
Unit 1 | 0 | 1 | 0 | 0
Student 6 | 0 | 1 | 0 | 0
Unit 1.1 | 0 | 0 | 0 | 1
Student 21 | 0 | 0 | 0 | 1
Student 33 | 0 | 0 | 0 | 0
Unit 1.1.1 | 0 | 0 | 0 | 0
Student 23 | 0 | 0 | 0 | 0
Unit 1.1.1.1 | 3 | 2 | 3 | 0
Student 10 | 0 | 0 | 0 | 0
Student 17 | 1 | 0 | 0 | 0
...
SQL Fiddle Demo
Do you need also the hierarchy to be sorted / visualized? At least this will calculate the sums, but the order of the data is pretty random :)
;with CTE as (
select S.StudentId as UnitID, S.UnitId as UnitParentID,
S.StudentID, 'Student' as Type
from Students S
union all
select U.UnitId, U.UnitParentId,
CTE.StudentId as StudentID, 'Unit ' as Type
from
Units U
join CTE
on U.UnitId = CTE.UnitParentId
)
select C.Type + ' ' + convert(varchar, C.UnitId),
sum(case when EventTypeId = 1 then 1 else 0 end) as E1,
sum(case when EventTypeId = 2 then 1 else 0 end) as E2,
sum(case when EventTypeId = 3 then 1 else 0 end) as E3,
sum(case when EventTypeId = 4 then 1 else 0 end) as E4
from
CTE C
left outer join events E on C.StudentId = E.StudentId
group by
C.Type, C.UnitId
SQL Fiddle
If you need also the hierarchy to be in order, you'll probably have add few extra CTEs to get the numbering from top down with something like #shA.t did. This gathers the hierarchy separately for each student, so it's not really possible to add the level numbers in a simple way.

Columns in sql query are not grouped

I've a problem with the following sql select query. The columns are not aggregated by the group by command.
SELECT
Dept.Name AS DeptName, COUNT (T.Id) AS TotalServiceNumber,
(Case when SS.Status <> 'Resolved' then COUNT (T.Id) end) AS UnresolvedNumber,
(Case when T.FixTime < '120' then COUNT(T.FixTime) end) AS ResolvedLessThanTwoHoursNumber,
(Case when T.FixTime > '120' then COUNT(T.FixTime) end) AS ResolvedMoreThanTwoHoursNumber,
FROM
dbo.Tickets AS T,
dbo.ServiceStatuses AS SS,
dbo.ComputerDesks AS Desk,
dbo.Personnels AS Person,
dbo.Departments AS Dept
WHERE
SS.Id = T.ServiceStatusId
AND T.ComputerDeskId = Desk.Id
AND Desk.PersonnelId = Person.Id
AND Person.DepartmentId = Dept.Id
GROUP BY
Dept.Name, SS.Status, T.FixTime
I'm getting the following result:
DeptName | TotalServiceNr | UnresolvedNumber | LessThanTwo | MoreThanTwo
DeptA | 8 | NULL | 8 | NULL
DeptB | 1 | 1 | NULL | 1
DeptC | 4 | NULL | NULL | 4
DeptA | 38 | NULL | NULL | 38
DeptB | 55 | NULL | 55 | NULL
DeptC | 7 | NULL | 7 | NULL
...
Expected result:
DeptName | TotalServiceNr | UnresolvedNumber | LessThanTwo | MoreThanTwo
DeptA | 46 | NULL | 8 | 38
DeptB | 56 | 1 | 55 | NULL
DeptC | 11 | NULL | 7 | 4
What I need to change to get the expected result?
try this query:
SELECT
Dept.Name AS DeptName, COUNT (T.Id) AS TotalServiceNumber,
sum(Case when SS.Status <> 'Resolved' then 1 else 0 end) AS UnresolvedNumber,
sum(Case when T.FixTime <= '120' then 1 else 0 end) AS ResolvedLessThanTwoHoursNumber,
sum(Case when T.FixTime > '120' then 1 else 0 end) AS ResolvedMoreThanTwoHoursNumber,
FROM
dbo.Tickets AS T,
dbo.ServiceStatuses AS SS,
dbo.ComputerDesks AS Desk,
dbo.Personnels AS Person,
dbo.Departments AS Dept
WHERE
SS.Id = T.ServiceStatusId
AND T.ComputerDeskId = Desk.Id
AND Desk.PersonnelId = Person.Id
AND Person.DepartmentId = Dept.Id
GROUP BY
Dept.Name
Try this
SELECT TotalServiceNumber, SUM(UnresolvedNumber), SUM(ResolvedLessThanTwoHoursNumber), SUM(ResolvedMoreThanTwoHoursNumber)
FROM (
SELECT
Dept.Name AS DeptName, COUNT (T.Id) AS TotalServiceNumber,
(Case when SS.Status <> 'Resolved' then COUNT (C.Id) end) AS UnresolvedNumber,
(Case when T.FixTime < '120' then COUNT(T.FixTime) end) AS ResolvedLessThanTwoHoursNumber,
(Case when T.FixTime > '120' then COUNT(T.FixTime) end) AS ResolvedMoreThanTwoHoursNumber,
FROM
dbo.Tickets AS T,
dbo.ServiceStatuses AS SS,
dbo.ComputerDesks AS Desk,
dbo.Personnels AS Person,
dbo.Departments AS Dept
WHERE
SS.Id = T.ServiceStatusId
AND T.ComputerDeskId = Desk.Id
AND Desk.PersonnelId = Person.Id
AND Person.DepartmentId = Dept.Id
GROUP BY Dept.Name, SS.Status, T.FixTime
) GROUPED
GROUP BY
TotalServiceNumber
SELECT
Dept.Name AS DeptName
, COUNT (T.Id) AS TotalServiceNumber
,COUNT(Case when SS.Status <> 'Resolved' then 1 ELSE NULL end) AS UnresolvedNumber
,COUNT(Case when T.FixTime < '120' then 1 ELSE NULL end) AS ResolvedLessThanTwoHoursNumber
,COUNT(Case when T.FixTime > '120' then 1 ELSE NULL end) AS ResolvedMoreThanTwoHoursNumber
FROM
dbo.Tickets AS T INNER JOIN dbo.ServiceStatuses AS SS
ON SS.Id = T.ServiceStatusId
INNER JOIN dbo.ComputerDesks AS Desk
ON T.ComputerDeskId = Desk.Id
INNER JOIN dbo.Personnels AS Person
ON Desk.PersonnelId = Person.Id
INNER JOIN dbo.Departments AS Dept
Person.DepartmentId = Dept.Id
GROUP BY Dept.Name
Also use ON syntax for your joins.