Using sub query in in group by sql server - sql

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

Related

using Query one results to run Query two

SELECT distinct
Pd.Cpd as ' accountnumber'
FROM [RQL_ALK_PMT].[Cts_opps] pd
INNER JOIN [RQL_ALK_PMT].[Cts_opps].dpo.cnms_id metg on metg.cnms_id=me.cnms_id
This code would result with this
Result
accountnumber
1332132
3213123
5641202
6412221
1233242
What I would like to do is when the code above gets the results my bottom code reads them and runs them trough its code. The common denominator here would be the account number because its running through a different table
SELECT
pm.AcctNumb as 'accountnumber'
, SUM(CASE WHEN pm.cusidIN ('cr') THEN 1 ELSE 0 END) AS CA
, SUM(CASE WHEN pm.cusidIN ('gb') THEN 1 ELSE 0 END) AS GB
, SUM(CASE WHEN pm.cusidIN ('tev','offev','Lastev') THEN 1 ELSE 0 END) AS chr
, SUM(CASE WHEN pm.cusidIN
('pm','pr','che' )
THEN 1 ELSE 0 END) AS Act
, SUM(CASE WHEN pm.cusidIN ('supev','tev') THEN 1 ELSE 0 END) AS Fulfillment
FROM ops.medadata pm WITH (NOLOCK)
INNER JOIN mw.pim_acct Ma with (nolock) ON ma.AcctNumb= pm.AcctNumb
Where pm.AcctNumb in ()
GROUP BY
pm.AcctNumb
I have tried doing this the code below but it doesnt seem to work
With counta as (
SELECT distinct
Pd.Cpd as ' accountnumber'
FROM [RQL_ALK_PMT].[Cts_opps] pd
INNER JOIN [RQL_ALK_PMT].[Cts_opps].dpo.cnms_id metg on metg.cnms_id=me.cnms_id
)
SELECT
pm.AcctNumb as 'accountnumber'
, SUM(CASE WHEN pm.cusidIN ('cr') THEN 1 ELSE 0 END) AS CA
, SUM(CASE WHEN pm.cusidIN ('gb') THEN 1 ELSE 0 END) AS GB
, SUM(CASE WHEN pm.cusidIN ('tev','offev','Lastev') THEN 1 ELSE 0 END) AS chr
, SUM(CASE WHEN pm.cusidIN
('pm','pr','che' )
THEN 1 ELSE 0 END) AS Act
, SUM(CASE WHEN pm.cusidIN ('supev','tev') THEN 1 ELSE 0 END) AS Fulfillment
FROM ops.medadata pm WITH (NOLOCK)
INNER JOIN mw.pim_acct Ma with (nolock) ON ma.AcctNumb= pm.AcctNumb
left join counta on Pm.accountnumber = counta.accountnumber
Where pm.AcctNumb in (counta.accountnumber)
GROUP BY
pm.AcctNumb
**im having issue with joining the two tables together**
IN is not an equivalent to a join - but you are treating that way.
Instead think of "IN this LIST" and the list could be supplied by you, or by a subquery e.g.
a list given by the query itself
select * from atable
where acol IN ('a','b','c') -- i.e. the list is hardcoded
or, using a subquery
SELECT ...etc.
WHERE pm.AcctNumb IN (
SELECT Pd.Cpd
FROM [RQL_ALK_PMT].[Cts_opps] pd
INNER JOIN [RQL_ALK_PMT].[Cts_opps].dpo.cnms_id metg on metg.cnms_id=me.cnms_id
)
or, if using a CTE
With counta as (
SELECT Pd.Cpd
FROM [RQL_ALK_PMT].[Cts_opps] pd
INNER JOIN [RQL_ALK_PMT].[Cts_opps].dpo.cnms_id metg on metg.cnms_id=me.cnms_id
)
SELECT ... etc.
WHERE pm.AcctNumb IN (
SELECT Cpd
FROM counta
)
note, it usually is not more efficient to use select distinct when forming a subquery to be used with an IN list.

Group by clause not returning the desired result

I have the following query that will pull the status of the courses enrolled for each user. I need to display a single record for that user that will represent the overall status of the courses. As you can see in the query below, it uses case statement to decide the prioritisation of the status. I have tried to use a group by clause but it still shows all the courses in the resultset. Could someone let me know what am I doing wrong in the query
DECLARE #Rep1 INT;
SET #Rep1 = 13119;
SELECT
cr.[CourseID]
, cr.[UserID]
,u.[Code]
,u.[DisplayName]
,t.[Name]
,cr.[CourseResultStatusID] AS [CourseResultStatusID]
,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 [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
)
group by cr.[CourseID], cr.[UserID], u.[Code], u.[DisplayName], t.[Name], [CourseResultStatusID],c.[PointsRequired],cr.[ExpiryDateTime]
The result of the query is below. As you can see there are 24 records. It is currently showing all the 6 courses per user. It should ideally only only 4 records.
REsultset that I am looking for

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)

Complex Case Statement Issue - Oracle SQL

Wrote the query below, but am getting multiplied amounts because the aggregation needs to occur before the case statements. Would love some advice on the best way to structure this.
Select Store, CUSTID, CUST.ID_CUST,
Sum(
CASE
WHEN Cust_Gift.Code_Status = 'C' AND Gift_Item.FLAG_STORE_LOC = 'N'
THEN Cust_Gift.AMT_PAID ELSE 0
END) GiftAmt,
Sum(
CASE WHEN Cust_Gift.Code_Status = 'C' AND Gift_Item.FLAG_STORE_LOC = 'Y'
THEN Cust_Gift.AMT ELSE 0
END) CustGiftAmt,
Sum(
CASE WHEN Cust_Coupon.Code_Status = 'C'
THEN Cust_Coupon.AMT
ELSE 0
END) CouponAmt,
Sum(CASE WHEN Cust_Sports.Status = 'C'
THEN Cust_Sports.AMT
ELSE 0
END) SportsAmt
FROM CUST
LEFT OUTER JOIN CUST_GIFT
ON CUST.ID_CUST = CUST_GIFT.ID_CUST
LEFT OUTER JOIN CUST_COUPON
ON CUST.ID_CUST = CUST_COUPON.ID_CUST
LEFT OUTER JOIN CUST_SPORTS
ON CUST.ID_CUST = CUST_SPORTS.ID_CUST
INNER JOIN GIFT_ITEM
ON CUST_GIFT.ID_GIFT_ITEM = GIFT_ITEM.ID_GIFT_ITEM
WHERE (STORE = 'M669098' OR STORE = 'M66923434' )
Group by CustID, Store, CUST.ID_CUST
This is one way you could do it:
SELECT cust.store,
cust.custid,
cust.id_cust,
gift.giftamt,
gift.custgift,
cpn.couponamt,
sprt.sportsamt
FROM cust
LEFT OUTER JOIN (SELECT id_cust,
SUM(CASE WHEN cg.code_status = 'C' AND gi.flag_store_loc = 'N' THEN cg.amt_paid END) giftamt,
SUM(CASE WHEN cg.code_status = 'C' AND gi.flag_store_loc = 'Y' THEN cg.amt_paid END) custgiftamt
FROM cust_gift cg
INNER JOIN gift_item gi ON cg.id_gift_item = gi.id_gift_item) gift ON cust.id_cust = gift.id_cust
LEFT OUTER JOIN (SELECT id_cust,
SUM(CASE WHEN code_status = 'C' THEN amt END) couponamt
FROM cust_coupon) cpn ON cust.id_cust = cpn.id_cust
LEFT OUTER JOIN (SELECT id_cust,
SUM(CASE WHEN status = 'C' THEN amt END) sportsamt
FROM cust_sports) sprt ON cust.id_cust = sprt.id_cust
WHERE (STORE = 'M669098' OR STORE = 'M66923434');

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;