Pivot SQL server results - sql-server

My result set looks like:
ICount Owners ProgramCount
1344 AA 1
408 AA 2
185 AA 3
87 AA 4
54 AA 5
644 EA 1
81 EA 2
18 EA 3
3 EA 4
2 EA 5
4419 JA 1
1461 JA 2
700 JA 3
375 JA 4
209 JA 5
and I'd like the results to be:
Owner Total ProgramCount 1 ProgramCount 2 ProgramCount 3 ProgramCount 4 ProgramCount 5
AA 2078 1344 408 185 87 54
EA 748 644 81 18 3 2
JA 7164 4419 1461 700 375 209
where the Total column is the sum of ProgramCount 1 through 5.
How would I build my SQL to accomplish this?

A simple pivot in concert with a sum() over()
Example
Select *
From (
Select [Owners]
,Item = concat('Program Count ',[ProgramCount])
,[ICount]
,[Total] = sum([ICount]) over(partition by [Owners])
from YourTable
) src
Pivot (sum([ICount]) for [Item] in ([Program Count 1],[Program Count 2],[Program Count 3],[Program Count 4],[Program Count 5]) ) pvt
Order By [Owners]
Returns

select v.Owners as Owners,
sum(v.ICount) as Total,
sum(case when v.ProgramCount = 1 then v.ICount else 0 end) as ProgramCount1,
sum(case when v.ProgramCount = 2 then v.ICount else 0 end) as ProgramCount2,
sum(case when v.ProgramCount = 3 then v.ICount else 0 end) as ProgramCount3,
sum(case when v.ProgramCount = 4 then v.ICount else 0 end) as ProgramCount4,
sum(case when v.ProgramCount = 5 then v.ICount else 0 end) as ProgramCount5
from (
QUERY_WITH_YOUR_RESULT_SET
) as v(ICount, Owners, ProgramCount)
group by v.Owners

According to #Максим Золотенко's answer, You can use Conditional aggregation query with a group by like below
SELECT Owners,
SUM(ICount) AS Total,
SUM(CASE WHEN ProgramCount = 1 THEN ICount ELSE 0 END) AS ProgramCount_1,
SUM(CASE WHEN ProgramCount = 2 THEN ICount ELSE 0 END) AS ProgramCount_2,
SUM(CASE WHEN ProgramCount = 3 THEN ICount ELSE 0 END) AS ProgramCount_3,
SUM(CASE WHEN ProgramCount = 4 THEN ICount ELSE 0 END) AS ProgramCount_4,
SUM(CASE WHEN ProgramCount = 5 THEN ICount ELSE 0 END) AS ProgramCount_5
FROM TempTable
GROUP BY Owners
Live demo on db<>fiddle
Output

Related

How to flatten this multiple rows into one?

I have data like this: (table name: Activities)
ActivityId CreatedOn TypeId
1 2017-01-01 1
1 2017-01-02 1
1 2017-01-02 2
2 2017-01-01 3
Where Type is a lookup value: (table name: Types)
TypeId Name
1 Question
2 Answer
3 Comment
Basically it's an activity history table.
I want to turn the above tables into a grouped sum row for types, for each ActivityId, like this:
ActivityId QuestionCount AnswerCount CommentCount
1 2 1 0
2 0 0 1
I know the answer is probably pretty simple, but it's eluding me for some reason.
Any help? Thanks in advance.
A simple join and conditional aggregation should do the trick (I suspect you were over-thinking it)
Select ActivityID
,QuestionCount = sum(case when Name='Question' then 1 else 0 end)
,AnswerCount = sum(case when Name='Answer' then 1 else 0 end)
,CommentCount = sum(case when Name='Comment' then 1 else 0 end)
From Activities A
Join Types B on A.TypeId=B.TypeId
Group By ActivityId
Returns
ActivityID QuestionCount AnswerCount CommentCount
1 2 1 0
2 0 0 1
You could also do it without the Join... Just less readable
Select ActivityID
,QuestionCount = sum(case when TypeId=1 then 1 else 0 end)
,AnswerCount = sum(case when TypeId=2 then 1 else 0 end)
,CommentCount = sum(case when TypeId=3 then 1 else 0 end)
From #Activities A
Group By ActivityId
You could also try a PIVOT
Select ActivityID
,[1] as QuestionCount
,[2] as AnswerCount
,[3] as CommentCount
From (Select ActivityId,TypeID,1 as Cnt From #Activities) A
Pivot (count(Cnt) For TypeId in ([1],[2],[3]) ) p

Count data using SQL Server 2008

I'm using SQL Server 2008 and I have a big database, I need to count the data for every manzana but every rows is 0 so I don't know how to do that
SELECT
Manzana,
SUM(CASE WHEN Manzana IN( 'CBrc','CBrc1', 'CBrc2') THEN 1 ELSE 0 END )AS CBrc,
SUM(CASE WHEN Manzana IN ('W1','W11','W12','W13','W14','W15','W16') THEN 1 ELSE 0 END) AS W1,
SUM(CASE WHEN Manzana IN('PC1','PC11') THEN 1 ELSE 0 END) AS PC1,
SUM(CASE WHEN Manzana IN ('CLu','CLU1') THEN 1 ELSE 0 END) AS CLu,
SUM(CASE WHEN Manzana IN('S3','S31') THEN 1 ELSE 0 END) AS S3,
SUM(CASE WHEN Manzana IN ('C2L') THEN 1 ELSE 0 END) AS C2L,
SUM(CASE WHEN Manzana IN ('PCA') THEN 1 ELSE 0 END) AS PCA,
SUM(CASE WHEN Manzana IN ('ADO') THEN 1 ELSE 0 END) AS AD,
SUM(CASE WHEN Manzana IN ('PRC') THEN 1 ELSE 0 END) AS CBu,
SUM(CASE WHEN Manzana IN('SIN') THEN 1 ELSE 0 END) AS SIN_ACCESO_A_INFORMACION
FROM
dbo.Hoja3$
GROUP BY
Manzana
I need to obtain something like this
Manzana CBrc W1 PC1 CLU S3 C2L
5445 8 11 0 0 0 0
4545 15 0 30 0 0 0
5455 21 0 5 3 2 0
7893 0 0 3 1 0 0
1566 100 4 1 0 0 80
You can't group by Manzana and not group by Manzana. Also, from the sample data, I can tell that you haven't provided enough information. Just from the first row:
Manzana CBrc W1 PC1 CLU S3 C2L
5445 8 11 0 0 0 0
If Manzana is 5445, then what column has the value CBrc? It can't be the Manzana column, but has to be some other column. In this vacuum of information, I'm going to call the mystery column Code.
Then try this (of course, you'll need to put all your code groups in):
WITH CodeGroupings AS (
SELECT * FROM (VALUES -- Do this in a permanent table instead!
('CBrc%', 'CBrc'), -- can use wildcards
('W1_', 'W1'), -- or single letter wildcards
('PC1', 'PC1'), -- or just put individual values
('PC11', 'PC1'), -- mapping to the same group as the previous line
('SIN', 'SIN_ACCESO_A_INFORMACION')
) M (CodePattern, CodeGroup)
), ManzanaCodeGroups AS (
SELECT
H.Manzana,
CG.CodeGroup
FROM
dbo.Hoja3$ H
CROSS APPLY (
SELECT TOP 1 *
FROM CodeGroupings CG
WHERE H.Code LIKE CG.CodePattern
) CG
)
SELECT
*
FROM
ManzanaCodeGroups
PIVOT (Count(*) FOR (CodeGroup IN CBrc, W1, PC1, SIN_ACCESO_A_INFORMACION)) P
;
After reading your comment "I try to count how many Cbrc,Pc1, Clu etc I have in every Manzana" I see the problem.
You're using the IN operator incorrectly.
To test fo the occurrence of a substring use the CHARINDEX function:
SELECT
Manzana,
SUM( CASE WHEN CHARINDEX( 'SIN', Manzana ) > 0 THEN 1 ELSE 0 END ) AS SIN,
SUM( CASE WHEN CHARINDEX( 'PCA', Manzana ) > 0 THEN 1 ELSE 0 END ) AS PCA,
...
FROM
Hoja3$
GROUP BY
Manzana

Combine multiple rows into one row with same number of columns

I have results that have multiple rows for priority counts for specific locations. I would like to simply turn those results into a single row to display the same information.
My current code is:
SELECT t.city_nm as CITY
,sum(case when h.priority = 1 then 1 else 0 end)as Priority1
,sum(case when h.priority = 2 then 1 else 0 end)as Priority2
,sum(case when h.priority = 3 then 1 else 0 end)as Priority3
from SHIPMENT h
INNER JOIN PET_EVT_LOG e
on h.svc_id = e.svc_id
INNER JOIN LOCATION t
ON t.city_id = e.term_id
INNER JOIN CUSTOMER u
ON h.ship_cust = u.cust_id
where u.cust_nm = 'CAL NATURAL'
and e.evt_cd = 'ARRIVAL'
and e.evt_dt_tm > date(current timestamp) - 7 day
GROUP BY t.city_nm, h.priority;
My results look like this:
CITY Priority1 Priority 2 Priority3
Atlanta 7 0 0
Atlanta 0 25 0
Atlanta 0 0 3
Baltimore 3 0 0
Baltimore 0 12 0
Baltimore 0 0 1
Detroit 9 0 0
Detroit 0 32 0
Detroit 0 0 5
Where there is a number count in one row, the other two fields are ALWAYS 0, so they should easily be combined to produce results that look like this:
CITY Priority1 Priority 2 Priority3
Atlanta 7 25 3
Baltimore 3 12 1
Detroit 9 32 5
try replacing
GROUP BY t.city_nm, h.priority;
by
GROUP BY t.city_nm;

Sql Query to find Counts

I have a table as below .
Id Product1 Product2 Product3
1 1 null null
2 1 2 null
3 3 1 null
4 2 3 1
Now I would like to write a query to count the entries with Product 1.
In the above case it is 2 for Product1 , 1 for Product2 and 1 for Product 3
I came up with a query something like this.
select
Count(Product1) +
Count(Product2) +
Count(Product3)
from
Table
where Product1 = 1
But it gives me an inaccurate result.
Is there a way I can get the number of occurances for each product ?
Group By
Desired output would be something like this :
ProductID Product1Count Product2Count Product3Count
1 2 1 1
2 1 1 0
3 1 1 0
select Count(CASE WHEN Product1 = 1 THEN 1 END) +
Count(CASE WHEN Product2 = 1 THEN 1 END) +
Count(CASE WHEN Product3 = 1 THEN 1 END)
from Table1
where 1 IN (Product1, Product2, Product3)
SQLFIddle Demo
The reason for adding this line: where 1 IN (Product1, Product2, Product3) is to count only on the affected rows, thus making it more faster than running through all records.
Something like this would work:
SELECT
SUM(CASE WHEN Product1 = 1 THEN 1 ELSE 0 END)
+ SUM(CASE WHEN Product2 = 1 THEN 1 ELSE 0 END)
+ SUM(CASE WHEN Product3 = 1 THEN 1 ELSE 0 END)
FROM Table

Issue Related to Query in SQL Server

I have three table in SQL Server 2008:
Students
StudentId Name
1 Ghanshyam
2 John
3 Pravin
Exams
ExamId ExamName
1 English
2 Math
3 SS
4 Mechanical
Marks
MarksId StudentId ExamId Marks
1 1 1 90
2 1 2 45
3 1 3 89
4 1 4 56
5 1 5 93
I want to get result display in following format:
Name English Math SS Mechnical
Ghanshyam 90 45 89 56
John 89 38 78 87
Pravin 98 40 48 38
How can I get the above result based on above three table
This is an example of Pivot tables. See
http://msdn.microsoft.com/en-us/library/ms177410.aspx
for the explanation of how to do it in MS SQL Server. Note that it is also possible to do this with standard SQL, though a bit more complicated.
Take a look at the pivot operator / Complex pivot example:
http://msdn.microsoft.com/en-us/library/ms177410.aspx
VendorID is your Name, EmpX your subjects.
Why don't you try something like this, if you do not want a pivot table?
SELECT s.Name,
SUM(CASE WHEN e.ExamName = 'English' THEN m.Marks ELSE 0 END)
/ NULLIF(COUNT(CASE WHEN e.ExamName = 'English' THEN 1 ELSE 0 END), 0) as English,
SUM(CASE WHEN e.ExamName = 'Math' THEN m.Marks ELSE 0 END)
/ NULLIF(COUNT(CASE WHEN e.ExamName = 'Math' THEN 1 ELSE 0 END), 0) as Math,
SUM(CASE WHEN e.ExamName = 'SS' THEN m.Marks ELSE 0 END)
/ NULLIF(COUNT(CASE WHEN e.ExamName = 'SS' THEN 1 ELSE 0 END), 0) as SS,
SUM(CASE WHEN e.ExamName = 'Mechanical' THEN m.Marks ELSE 0 END)
/ NULLIF(COUNT(CASE WHEN e.ExamName = 'Mechanical' THEN 1 ELSE 0 END), 0) as Mechanical
FROM students s, marks m, exams e
WHERE m.StudentID = s.StudentID
AND m.ExamID = e.ExamID

Resources