Display SQL Data From Row to Column - sql

My SQL statement is list as below:
SELECT Count(DISTINCT A.LM_PERSON_ID) AS HEAD_COUNT
,A.LM_STATUS
,To_Char(A.LM_STATUS_CHANGE_DT,'YYYY') AS YEAR
,B.LM_COURSE_NAME AS COURSE_NAME
FROM LM_ENRLOLMENT A
,LM_COURSE_TBL B
WHERE A.LM_STATUS='COMP'
AND A.LM_COURSE_ID=B.LM_CI_ID
GROUP BY A.LM_STATUS_CHANGE_DT,LM_STATUS,B.LM_COURSE_NAME
The example output I would like to display was:
COURSE_NAME 2010 2011 2012
A 4 5 1
B 2 1 1
C 6 0 3
D 1 1 2
But the main problem I am facing is that LM_STATUS_CHANGE_DT is dynamic data. Is there anyone that can show me how I could do this?

You did not specify what RDBMS you are using but you should be able to use the following in all versions:
SELECT
B.LM_COURSE_NAME AS COURSE_NAME,
count(DISTINCT case when To_Char(A.LM_STATUS_CHANGE_DT,'YYYY') = '2010' then A.LM_PERSON_ID end) as Year2010,
count(DISTINCT case when To_Char(A.LM_STATUS_CHANGE_DT,'YYYY') = '2011' then A.LM_PERSON_ID end) as Year2011,
count(DISTINCT case when To_Char(A.LM_STATUS_CHANGE_DT,'YYYY') = '2012' then A.LM_PERSON_ID end) as Year2012
FROM LM_ENRLOLMENT A
INNER JOIN LM_COURSE_TBL B
ON A.LM_COURSE_ID=B.LM_CI_ID
WHERE A.LM_STATUS='COMP'
GROUP BY B.LM_COURSE_NAME
If you are using an RDBMS that has the PIVOT function (SQL Server 2005+/Oracle 11g+) then your code will be similar to this:
SELECT *
FROM
(
SELECT DISTINCT B.LM_COURSE_NAME,
To_Char(A.LM_STATUS_CHANGE_DT,'YYYY') As Year,
A.LM_PERSON_ID
FROM LM_ENRLOLMENT A
INNER JOIN LM_COURSE_TBL B
ON A.LM_COURSE_ID=B.LM_CI_ID
WHERE A.LM_STATUS='COMP'
) src
PIVOT
(
count(LM_PERSON_ID)
for Year in ('2010', '2011', '2012')
) piv

Related

aliasing pivot column

i am trying to alias the pivot column to scenario1, scenario2, scenario3 instead of 1,2,3. I am getting error.
select *
from (select *
from (select s.campaign_id campaign_id, s.scenario_index scenario_index
from scenario s, campaign c where s.campaign_id = c.campaign_id)
pivot (max(scenario_index)for scenario_index in (1,2,3))
)a
thank you, aggregation gives the result with alias now. The requirement i have is to combine these columns with another query which is
select CASE WHEN AWARD_TYPE = 0 THEN award_rate||' points'
when AWARD_TYPE = 1 then Award_rate||' %'
when award_type=2 then RATIO_POINTS||' points per '||RATIO_MON_UNIT||' AED' End
from points_rule p
where c.pt_basic_rule_id = p.point_rule_id ) as pool_awards,
this query comes as a column and then the scenario1, 2,3 should come as 3 columns with the value of the pool_award based on the campaign_id
Just use conditional aggregation:
select s.campaign_id,
max(case when scenario_index = 1 then 1 end) as scenario1,
max(case when scenario_index = 2 then 1 end) as scenario2,
max(case when scenario_index = 3 then 1 end) as scenario3
from scenario s join
campaign c
on s.campaign_id = c.campaign_id
group by campaign_id;
You can use an alias in IN clause of the PIVOT as follows:
select *
from (select *
from (select s.campaign_id campaign_id, s.scenario_index scenario_index
from scenario s, campaign c where s.campaign_id = c.campaign_id)
pivot (max(scenario_index)for scenario_index in (1 as scenario1,2 as scenario2,3 as scenario3))
)a

Pivot Multiple columns together in SQL

I've table like this
I need to get a result like this
RT Team PI Committed Done-Partial Done-Full
----------------------------------------------------------------
ART1 Team1 10 5 1 3
ART2 Team2 7 5 4 1
-----------------------------------------------------------------------
The way I tried is as follows
;with RecentPI as(
select * from (
select rt,Team,pi,[Finish Date],DENSE_RANK() over( partition by rt order by [Finish Date] desc) PIRank from Schedule_Manual S inner join TFS_ARTs_Teams T on T.ART=S.RT
group by RT,Team,PI,[Finish Date]
)tbl
where PIRank=1
)
select * from (select Obj.RT,Obj.[TFS Team], Obj.Type,Obj.PI,[PI Status] from Objectives Obj inner join RecentPI RP on RP.RT=Obj.RT and RP.Team=Obj.[TFS Team] and RP.PI=Obj.PI) as query
PIVOT (count(type) for [Type] in ([Committed])) p1
PIVOT (Count([PI Status]) for [pi status] in ([Done-Partial],[Done-Full])) p2
But it doesnt seems to be correct and also Im not getting full columns in the query. Sorry Im very beginner with SQL Pivot
You can Use this simple Query...your problem will be solved....
select RT,Team,[PI],
sum(case when [Type] = 'Committed' then 1 else 0 end) AS 'Committed',
sum(case when PIStatus = 'Done-Partial' then 1 else 0 end) AS 'Done-Partial',
sum(case when PIStatus = 'Done-Full' then 1 else 0 end) AS 'Done-Full'
from tbl_Pivot
group by RT,Team,[PI]
Output:-

SQLite3: Return a NULL if no records exist in SUM()

I would like to SUM() while also using a WHERE but when there are no records found for a certain ID I would like it to return NULL instead of just not returning anything.
Initial Code:
SELECT
ID,
SUM(CASE WHEN EVENTS = 3 THEN 1 ELSE 0 END)
FROM Events_ID
WHERE
YEAR = 2012
GROUP BY ID
This would not return an ID if there were no events for it in 2012.
I then changed it to the following that appears to work but is around 100x slower!
SELECT
ID,
(SELECT
SUM(CASE WHEN EVENTS = 3 THEN 1 ELSE 0 END)
FROM EVENTS_ID r WHERE r.ID = t.ID AND r.YEAR = 2012)
FROM (SELECT * FROM Events_ID GROUP BY ID) as t;
Is there anyway to get the output of the second query nearer to the speed of the first?
Is this what you want?
SELECT ID,
SUM(CASE WHEN EVENTS = 3 AND YEAR = 2012 THEN 1 END)
FROM Events_ID
GROUP BY ID;
This will return all ids, with a NULL as a second value if no events match both conditions.

2 Conditions for the same column in a SQl query

How can i get the distinct dates in a table where R.TypeofDayID = 2 and it should not include dates with R.TypeofDayID = 1
I can get all the distinct dates for R.TypeofDayID = 2 using the below query but i am not sure how i can add a condition to get dates where TypeofDayID = 2 and the date should not have TypeofDayID = 1 in any row.
Select count(distinct(R.Date)) from RepInfo R
where R.TypeofDayID = 2 and Month(R.Date) = 2 and Year(R.Date) = 2013
I hope i am clear. This is in SQL Server 2005. Thank you in advance!
Select R.Date, count(*) as cnt
from RepInfo R
where Month(R.Date) = 2 and Year(R.Date) = 2013
group by R.Date
having sum(case when TypeofDayID <> 2 then 1 else 0 end) = 0
Why are you using a COUNT() function in your select statement if you want the the output to be a list of distinct dates? Would you get your desired result from changing your select to something like this:
Select distinct(R.Date)

Select Distinct Attribute and Print out Count of another even when the count is 0

I don't quite know how I should describe the problem for title, but here's my question.
I have a table named hello with two columns named time and state.
Time | State
Here's an example of the data I have
1 DC
1 VA
1 VA
2 DC
2 MD
3 MD
3 MD
3 VA
3 DC
I would like to get all the possible time and the count of "VA" (0 if "VA" doesn't appear at the time)
The output would look like this
Time Number
1 2
2 0
3 1
I tried to do
SELECT DISTINCT time,
COUNT(state) as Number
FROM hello
WHERE state = 'VA'
GROUP BY time
but it doesn't seem to work.
This is a conditional aggregation:
select time, sum(case when state = 'VA' then 1 else 0 end) as NumVA
from hello
group by time
I want to add that you should never use distinct when you have a group by. The two are redundant. Distinct as a keyword is not even needed in the SQL language; semantically, it is just shorthand for grouping by all the columns.
SELECT TIME,
SUM(CASE WHEN State = 'VA' THEN 1 ELSE 0 END)
FROm tableName
GROUP BY Time
SQLFiddle Demo
One rule of thumb is to get your counts first and put them into a temp for use later.
See below:
Create table temp(Num int, [state] varchar(2))
Insert into temp(Num,[state])
Select 1,'DC'
UNION ALL
Select 1,'VA'
UNION ALL
Select 1,'VA'
UNION ALL
Select 2,'DC'
UNION ALL
Select 2,'MD'
UNION ALL
Select 3,'MD'
UNION All
Select 3,'MD'
UNION ALL
Select 3,'VA'
UNION ALL
Select 3,'DC'
Select t.Num [Time],t.[State]
, CASE WHEN t.[state] = 'VA' THEN Count(t.[State]) ELSE 0 END [Number]
INTO #temp2
From temp t
Group by t.Num, t.[state]
--drop table #temp2
Select
t2.[time]
,SUM(t2.[Number])
From #temp2 t2
group by t2.[time]