Display query results using pivot - sql

I have the below query which i to display the results using a PIVOT so that the results are displayed in one row.
With T1 As
(EXT Code
),
T2 AS (
SELECT p.SId, p.TransType, Amount =SUM(p.Amount)
FROM T1 p
GROUP BY p.SId, p.TransType
)
SELECT m.SNo, m.Name, t.TransType,
CASE WHEN t.TransType ='PAYCM' THEN t.Amount ELSE 0 END AS 'GROSS CM',
CASE WHEN t.TransType ='PAYYTD' THEN t.Amount ELSE 0 END AS 'GROSS YTD',
CASE WHEN t.TransType ='TAXCM' THEN t.Amount ELSE 0 END AS 'Tax CM',
CASE WHEN t.TransType ='TAXYTD' THEN t.Amount ELSE 0 END AS 'Tax YTD'
FROM Master m INNER JOIN T2 t ON t.PId = m.Id

If you want one row, then use aggregation and remove the non-aggregated columns:
SELECT SUM(CASE WHEN t.TransType = 'PAYCM' THEN t.Amount ELSE 0 END) AS GROSS _CM,
SUM(CASE WHEN t.TransType = 'PAYYTD' THEN t.Amount ELSE 0 END) AS GROSS_YTD,
SUM(CASE WHEN t.TransType = 'TAXCM' THEN t.Amount ELSE 0 END) AS Tax_CM,
SUM(CASE WHEN t.TransType = 'TAXYTD' THEN t.Amount ELSE 0 END) AS Tax_YTD
FROM Master m INNER JOIN
T2 t
ON t.PId = m.Id;

Related

Duplicate data when working with multiple tables. Clarification needed

I have a very simple table as shown when query returning clean data select * from Income where symbol = 'AAPL' and statementitem = 'Revenues' and periodtype="Annual";
--
When I attempt to put together a report, I get 0 from someplace. How can I remove the 0 to get a clean output? Where do these 0s come from?
DROP TABLE IF EXISTS _vars;
CREATE TABLE _vars(symbol);
INSERT INTO _vars(symbol) VALUES ('AAPL');
SELECT distinct a.yearmonth, a.symbol, periodtype,
case when a.statementitem = 'Revenues' AND a.periodtype = 'Annual' then (CASE WHEN (a.value is null or a.value = '') then 0 ELSE a.value END) else 0 end Revenue,
case when a.statementitem = 'Gross Profit' AND a.periodtype = 'Annual' then (CASE WHEN (a.value is null or a.value = '') then 0 ELSE a.value END) else 0 end GrossProfit,
case when a.statementitem = 'Selling General & Admin Expenses' AND a.periodtype = 'Annual' then (CASE WHEN (a.value is null or a.value = '') then 0 ELSE a.value END) else 0 end GrossProfit
FROM _vars
INNER JOIN Income a ON a.symbol = _vars.symbol and a.periodtype = 'Annual'
Your 1st query contains 3 conditions:
WHERE symbol = 'AAPL' AND statementitem = 'Revenues' AND periodtype = 'Annual'
and the result is 10 rows.
Your 2nd query joins _vars to the table and since _vars contains only 1 row with the column symbol having value 'AAPL' and you also apply the condition:
and a.periodtype = 'Annual'
in the ON clause, you are covering only 2 of the conditions of the 1st query.
You do not apply the condition:
statementitem = 'Revenues'
you are just checking it in:
case when a.statementitem = 'Revenues' AND .....
Checking a condition does not apply it.
This means that you get more rows in the results that are coming from all the rows that do not have 'Revenues' in the column statementitem and the CASE expression returns 0 for these rows in the column Revenue.
Edit:
You should use conditional aggregation:
SELECT a.yearmonth, a.symbol, a.periodtype,
COALESCE(MAX(CASE WHEN a.statementitem = 'Revenues' THEN a.value END), 0) Revenue,
COALESCE(MAX(CASE WHEN a.statementitem = 'Gross Profit' THEN a.value END), 0) GrossProfit,
COALESCE(MAX(CASE WHEN a.statementitem = 'Selling General & Admin Expenses' THEN a.value END), 0) [Selling General & Admin Expenses]
FROM _vars INNER JOIN Income a
ON a.symbol = _vars.symbol AND a.periodtype = 'Annual'
GROUP BY a.yearmonth, a.symbol, a.periodtype
You are getting 0 because of the below case statement. If your value is null and statementitem is not 'Revenues' and periodtype is not 'Annual', you are a making it as 0
case when a.statementitem = 'Revenues' AND a.periodtype = 'Annual'
then (CASE WHEN (a.value is null or a.value = '') then 0 ELSE a.value END) else 0
You can get rid of these if you don't want 0's in your result.
This will give you without 0's but with nulls,
SELECT distinct a.yearmonth, a.symbol, periodtype,
a.value as Revenue
FROM _vars
inner JOIN Income a ON a.symbol = _vars.symbol
where a.statementitem = 'Revenues' and a.periodtype = 'Annual'
This query will give you no nulls,
SELECT distinct a.yearmonth, a.symbol, periodtype,
a.value as Revenue
FROM _vars
inner JOIN Income a ON a.symbol = _vars.symbol
where a.statementitem = 'Revenues' and a.periodtype = 'Annual'
and (a.value is null or a.value = '')
Without Inner join,
SELECT distinct a.yearmonth, a.symbol, periodtype,
a.value as Revenue
from Income a
where a.statementitem = 'Revenues' and a.periodtype = 'Annual'
and (a.value is null or a.value = '')
and a.symbol in ('AAPL');
these duplicate data are because of records that are (AAPL,Annual) but are not (Revenues).you should move the condition of statementitem in where cluse or in join condition:
SELECT distinct a.yearmonth, a.symbol, periodtype,isnull(a.value,0) as Revenue
FROM _vars
inner JOIN Income a ON a.symbol = _vars.symbol
where a.statementitem = 'Revenues' and a.periodtype = 'Annual'
or
SELECT distinct a.yearmonth, a.symbol, periodtype,isnull(a.value,0) as revenue
FROM _vars
inner JOIN Income a ON a.symbol = _vars.symbol
and a.statementitem = 'Revenues' and a.periodtype = 'Annual'
Please use below query,
With Join
SELECT distinct a.yearmonth, a.symbol, periodtype,
case when a.statementitem = 'Revenues' then (CASE WHEN (a.value is null or a.value = '') then 0 ELSE a.value END) else 0 end Revenue,
case when a.statementitem = 'Gross Profit' then (CASE WHEN (a.value is null or a.value = '') then 0 ELSE a.value END) else 0 end GrossProfit,
case when a.statementitem = 'Selling General & Admin Expenses' then (CASE WHEN (a.value is null or a.value = '') then 0 ELSE a.value END) else 0 end GrossProfit
FROM _vars
INNER JOIN Income a ON a.symbol = _vars.symbol
where a.periodtype = 'Annual'
Without Join
SELECT distinct a.yearmonth, a.symbol, periodtype,
case when a.statementitem = 'Revenues' then (CASE WHEN (a.value is null or a.value = '') then 0 ELSE a.value END) else 0 end Revenue,
case when a.statementitem = 'Gross Profit' then (CASE WHEN (a.value is null or a.value = '') then 0 ELSE a.value END) else 0 end GrossProfit,
case when a.statementitem = 'Selling General & Admin Expenses' then (CASE WHEN (a.value is null or a.value = '') then 0 ELSE a.value END) else 0 end GrossProfit
FROM Income a
where a.periodtype = 'Annual'
and a.symbol in ('AAPL');

How to join two sub queries and find the difference of attribute values in SQL

From the below query, I want to know how to combine these two sub-queries and also find the difference of values of the attributes specified for two different years.
I had tried joining them using joins, but I do not have a common attribute on which I can combine them as they are for two different years. I need to find the difference in order to compute the change as seen in the attached picture. Can anyone help?
(select (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD,1,4)))-1 as 'Year1',
SUM(CASE WHEN dh.HOME = 'f' THEN 1 else 0 END) as 'foriegn1',
SUM(CASE WHEN dh.HOME = 'o' THEN 1 else 0 END) AS 'outofstate1',
SUM(CASE WHEN dh.HOME = 'i' THEN 1 else 0 END) AS 'texas1',
SUM(CASE WHEN dh.HOME = 'u' THEN 1 else 0 END) AS 'Unknown1',
COUNT(*) as Totalenrollment
FROM dw_enrollment_F d
inner join dim_Time t
on d.TIME_KEY = t.TIME_KEY
inner join dim_Home dh
on d.HOME_KEY = dh.HOME_KEY
inner join dim_Student_Level sl
on d.STUDENT_LEVEL_KEY = sl.STUDENT_LEVEL_KEY
where t.ACADEMIC_PERIOD_all =20162
and t.ACADEMIC_PERIOD_ALL not in('20157','20165','20168','20169','20167')
GROUP BY (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD,1,4)) ) -1)
(select (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD,1,4)))-1 as 'Year2',
SUM(CASE WHEN dh.HOME = 'f' THEN 1 else 0 END) as 'foriegn2',
SUM(CASE WHEN dh.HOME = 'o' THEN 1 else 0 END) AS 'outofstate2',
SUM(CASE WHEN dh.HOME = 'i' THEN 1 else 0 END) AS 'texas2',
SUM(CASE WHEN dh.HOME = 'u' THEN 1 else 0 END) AS 'Unknown2',
COUNT(*) as Totalenrollment2
FROM dw_enrollment_F d
inner join dim_Time t
on d.TIME_KEY = t.TIME_KEY
inner join dim_Home dh
on d.HOME_KEY = dh.HOME_KEY
inner join dim_Student_Level sl
on d.STUDENT_LEVEL_KEY = sl.STUDENT_LEVEL_KEY
where t.ACADEMIC_PERIOD_all = 20172
and t.ACADEMIC_PERIOD_ALL not in('20157','20165','20168','20169','20167')
GROUP BY (CONVERT(INT,SUBSTRING(ACADEMIC_PERIOD,1,4)) ) -1)

Using sub query in in group by sql server

Hello everyone I would like to use sub query as code bellow but it get error I would like to to ask you that I how can i do this. Thanks!
SELECT HR_EMPMAST.DEPT,HR_DEPARTMENT.DESCRIPTION AS DEPARTMENT,HR_JOBFUNCTION.CODE,HR_JOBFUNCTION.DESCRIPTION AS POSITION,
COUNT(HR_EMPMAST.EMPCODE) ACTUAL,
SUM(CASE WHEN HR_EMPMAST.SEX = 'M' THEN 1 ELSE 0 END) AS M,
SUM(CASE WHEN HR_EMPMAST.SEX = 'F' THEN 1 ELSE 0 END) AS F,SUM(CASE WHEN HR_EMPMAST.EMPTYPE='LOCAL' THEN 1 ELSE 0 END) AS LOCALEMP,
SUM(CASE WHEN HR_EMPMAST.EMPTYPE='EXPAT' THEN 1 ELSE 0 END) AS EXPATEMP--,
(SELECT EMPNO FROM HR_HEADCOUNT WHERE POSITION=HR_EMPMAST.JOBCODE AND INMONTH=1 AND INYEAR=2017) AS EMPNO
FROM HR_EMPMAST
LEFT JOIN HR_DEPARTMENT
ON HR_EMPMAST.DEPT = HR_DEPARTMENT.CODE
LEFT JOIN HR_JOBFUNCTION
ON HR_EMPMAST.JOBCODE=HR_JOBFUNCTION.CODE
WHERE HR_EMPMAST.CAREERDESC <> 'TERMIMATE'
GROUP BY HR_EMPMAST.DEPT,HR_DEPARTMENT.DESCRIPTION,HR_JOBFUNCTION.CODE,HR_JOBFUNCTION.DESCRIPTION
At first, please, use table aliases.
Second: you need to add ALL columns from SELECT to GROUP BY (but not ones in SUM and COUNT functions).
Third: you got strange EMPNO select. Maybe better way is to use JOIN?
Try to use this one:
SELECT e.DEPT,
d.DESCRIPTION AS DEPARTMENT,
jf.CODE,
jf.DESCRIPTION AS POSITION,
COUNT(e.EMPCODE) ACTUAL,
SUM(CASE WHEN e.SEX = 'M' THEN 1 ELSE 0 END) AS M,
SUM(CASE WHEN e.SEX = 'F' THEN 1 ELSE 0 END) AS F,
SUM(CASE WHEN e.EMPTYPE='LOCAL' THEN 1 ELSE 0 END) AS LOCALEMP,
SUM(CASE WHEN e.EMPTYPE='EXPAT' THEN 1 ELSE 0 END) AS EXPATEMP,
hc.EMPNO
FROM HR_EMPMAST e
LEFT JOIN HR_DEPARTMENT d
ON e.DEPT = d.CODE
LEFT JOIN HR_JOBFUNCTION jf
ON e.JOBCODE = jf.CODE
LEFT JOIN HR_HEADCOUNT hc
ON hc.POSITION = e.JOBCODE AND hc.INMONTH=1 AND hc.INYEAR=2017
WHERE e.CAREERDESC <> 'TERMIMATE'
GROUP BY e.DEPT,
d.DESCRIPTION,
jf.CODE,
jf.DESCRIPTION,
hc.EMPNO
Try this below query or include HR_EMPMAST.JOBCODE in group by clause...
SELECT HR_EMPMAST.DEPT,HR_DEPARTMENT.DESCRIPTION AS DEPARTMENT,HR_JOBFUNCTION.CODE,HR_JOBFUNCTION.DESCRIPTION AS POSITION,
COUNT(HR_EMPMAST.EMPCODE) ACTUAL,
SUM(CASE WHEN HR_EMPMAST.SEX = 'M' THEN 1 ELSE 0 END) AS M,
SUM(CASE WHEN HR_EMPMAST.SEX = 'F' THEN 1 ELSE 0 END) AS F,SUM(CASE WHEN HR_EMPMAST.EMPTYPE='LOCAL' THEN 1 ELSE 0 END) AS LOCALEMP,
SUM(CASE WHEN HR_EMPMAST.EMPTYPE='EXPAT' THEN 1 ELSE 0 END) AS EXPATEMP,
em.EMPNO AS EMPNO
FROM HR_EMPMAST
LEFT JOIN (SELECT POSITION, EMPNO FROM HR_HEADCOUNT WHERE INMONTH=1 AND INYEAR=2017) em on em.POSITION=HR_EMPMAST.JOBCODE
LEFT JOIN HR_DEPARTMENT
ON HR_EMPMAST.DEPT = HR_DEPARTMENT.CODE
LEFT JOIN HR_JOBFUNCTION
ON HR_EMPMAST.JOBCODE=HR_JOBFUNCTION.CODE
WHERE HR_EMPMAST.CAREERDESC <> 'TERMIMATE'
GROUP BY HR_EMPMAST.DEPT,HR_DEPARTMENT.DESCRIPTION,HR_JOBFUNCTION.CODE,HR_JOBFUNCTION.DESCRIPTION

Case sql not working

I have a select statement I am trying to make for a report. I have it pulling data and everything I need but I noticed that since I have to use the group by it is dropping off rows that do not exist in a table. How can I stop this or make it work.
SELECT Sum(CASE WHEN direction = 'I' THEN 1 ELSE 0 END) InBound,
Sum(CASE WHEN direction = 'O' THEN 1 ELSE 0 END) OutBound,
Sum(CASE WHEN direction = 'I' THEN p.duration ELSE 0 END) InBoundTime,
Sum(CASE WHEN direction = 'O' THEN p.duration ELSE 0 END) OutBoundTime,
u.fullname,
( CASE
WHEN EXISTS (SELECT g.goalamount
FROM [tblbrokergoals] AS g
WHERE ( g.goaldate BETWEEN
'2016-03-21' AND '2016-03-27' ))
THEN
g.goalamount
ELSE 0
END ) AS GoalAmount
FROM [tblphonelogs] AS p
LEFT JOIN [tblusers] AS u
ON u.fullname = p.phonename
LEFT OUTER JOIN [tblbrokergoals] AS g
ON u.fullname = g.brokername
WHERE ( calldatetime BETWEEN '2016-03-21' AND '2016-03-27' )
AND ( u.userid IS NOT NULL )
AND ( u.direxclude <> '11' )
AND u.termdate IS NULL
AND ( g.goaldate BETWEEN '2016-03-21' AND '2016-03-27' )
GROUP BY u.fullname,
g.goalamount;
This works and grabs all the data when the user is in BrokerGoals but, when the user is not in broker goals it just deletes that row on the returned result set. How can I get it so when the user doesnt not exist in the brokergoals table to set that value as 0 or -- so the row does not get deleted.
If you have a brokers table then you can use it for your left join
SELECT b.broker_id, ....
FROM brokers b
LEFT JOIN .... ALL YOUR OTHER TABLES
....
GROUP BY b.broker_id, ....
If your brokers has duplicate names then use
SELECT b.broker_id, ....
FROM (SELECT DISTINCT broker_id
FROM brokers) b
LEFT JOIN .... ALL YOUR OTHER TABLES
....
GROUP BY b.broker_id, ....
SELECT u.FullName,
SUM(CASE WHEN Direction = 'I' THEN 1 ELSE 0 END) AS InBound,
SUM(CASE WHEN Direction = 'O' THEN 1 ELSE 0 END) OutBound,
SUM(CASE WHEN Direction = 'I' THEN p.Duration ELSE 0 END) InBoundTime,
SUM(CASE WHEN Direction = 'O' THEN p.Duration ELSE 0 END) OutBoundTime,
CASE WHEN EXISTS (
SELECT g.GoalAmount
FROM [Portal].[dbo].[tblBrokerGoals] AS g
WHERE g.GoalDate BETWEEN '2016-03-21' AND '2016-03-27'
AND u.FullName = g.BrokerName
) THEN (
SELECT g.GoalAmount
FROM [Portal].[dbo].[tblBrokerGoals] AS g
WHERE g.GoalDate BETWEEN '2016-03-21' AND '2016-03-27'
AND u.FullName = g.BrokerName
) ELSE '0' END AS GoalAmount
FROM [Portal].[dbo].[tblUsers] AS u
LEFT JOIN [Portal].[dbo].[tblPhoneLogs] AS p
ON u.FullName = p.PhoneName
WHERE u.UserID IS NOT NULL
AND u.DirExclude <> '11'
AND u.TermDate IS NULL
AND p.CallDateTime BETWEEN '2016-03-21' AND '2016-03-27'
GROUP BY u.FullName
This is what I ended up doing to fix my problem. I added the Case When Exists statement and in the then statement did the select else it is 0.
Have you tried replacing ( CASE
WHEN EXISTS (SELECT g.goalamount
FROM [tblbrokergoals] AS g
WHERE ( g.goaldate BETWEEN
'2016-03-21' AND '2016-03-27' ))
THEN
g.goalamount
ELSE 0
END ) AS GoalAmount
to just g.goalamount, as you already have that date condition in where clause

SQL QUERY with subquery Optimization

how can i optimize these query
SELECT
mp.ProviderName
,(SELECT count(mc.ClaimSubmissionID) FROM dbo.MST_Claim mc WHERE mc.HeaderID=mpach.HeaderID AND mc.IsActive=1) AS total_claim
,(SELECT count(mc.ClaimSubmissionID) FROM dbo.MST_Claim mc WHERE mc.HeaderID=mpach.HeaderID AND mc.op=1) AS total_op
,(SELECT count(mc.ClaimSubmissionID) FROM dbo.MST_Claim mc WHERE mc.HeaderID=mpach.HeaderID AND mc.ip=1) AS total_ip
FROM dbo.MST_PriorAuthorization_Claim_Header mpach
INNER JOIN dbo.MS_Provider mp ON mp.Provider_ID = mpach.Provider_ID
Use Sum of CASE Statements to avoid all those subqueries.
SELECT
mp.ProviderName,
SUM(CASE WHEN mc.IsActive=1 THEN 1 ELSE 0 END ) AS total_claim,
SUM(CASE WHEN mc.op=1 THEN 1 ELSE 0 END ) AS total_op,
SUM(CASE WHEN mc.ip=1 THEN 1 ELSE 0 END ) AS total_ip
FROM dbo.MST_PriorAuthorization_Claim_Header mpach
INNER JOIN dbo.MS_Provider mp ON mp.Provider_ID = mpach.Provider_ID
INNER JOIN dbo.MST_Claim mc ON mc.HeaderID=mpach.HeaderID
You can modify your query using a CASE statement like below
SELECT
mp.ProviderName
,sum(case when mc.IsActive=1 then mc.ClaimSubmissionID else 0 end) AS total_claim,
sum(case when mc.op=1 then mc.ClaimSubmissionID else 0 end) AS total_op
sum(case when mc.ip=1 then mc.ClaimSubmissionID else 0 end) AS total_ip
FROM dbo.MST_PriorAuthorization_Claim_Header mpach
INNER JOIN dbo.MS_Provider mp ON mp.Provider_ID = mpach.Provider_ID
JOIN dbo.MST_Claim mc ON mc.HeaderID = mpach.HeaderID;