SQL WHERE statement is not working with RIGHT JOIN - sql

I have the below SQL query, but the problem is that the WHERE statement is not working properly with RIGHT JOIN:
SELECT COUNT(*) no_of_application_by_status, applicationStatusName
FROM `Application` `a`
right JOIN `ApplicationStatus` `ass` ON `ass`.`applicationStatusId`=`a`.`applicationStatusId`
WHERE `applicationTypeId` = '40007'
GROUP BY `ass`.`applicationStatusId`
I want to get the applicationStatusName where no_of_application_by_status = 0

You have to put the where condition to the on clause:
SELECT COUNT(*) no_of_application_by_status, applicationStatusName
FROM `Application` `a`
right JOIN `ApplicationStatus` `ass` ON `ass`.`applicationStatusId`=`a`.`applicationStatusId`
and `applicationTypeId` = '40007'
GROUP BY `ass`.`applicationStatusId`
If you do not do it, the joind result will be filtered by the where condition.

Use Having you want to fetch group count = 0 OR if you want to count only the records where no_of_application_by_status = 0 then use AND condition in WHERE
For Group Count = 0
SELECT COUNT(*) no_of_application_by_status,
applicationStatusName
FROM Application a
RIGHT JOIN ApplicationStatus ass ON ass.applicationStatusId=a.applicationStatusId
WHERE applicationTypeId = '40007'
HAVING COUNT(*) = 0
GROUP BY ass.applicationStatusId
OR count of no_of_application_by_status = 0
SELECT COUNT(*) no_of_application_by_status,
applicationStatusName
FROM Application a
RIGHT JOIN ApplicationStatus ass ON ass.applicationStatusId=a.applicationStatusId
WHERE applicationTypeId = '40007' AND no_of_application_by_status = 0
GROUP BY ass.applicationStatusId

Related

Group by + Select Case

I try to query this code but i got the error massage.
"ORA-00979: not a GROUP BY expression"
Can we use case SUM and Max in group by function.
SELECT PLAN.MFGNO "MFGNO",
PROCESSMASTER.PART_NO "PART_NO",
PROCESS.MED_PROC_CD "M_PROCESS",
MAX(PLAN.PLAN_START) "PLAN_START_DATE",
MAX(PLAN.PLAN_END) "PLAN_END_DATE",
MAX(PLAN.ACT_START) "ACT_START_DATE",
MAX(PLAN.ACT_END) "ACT_END_DATE",
(CASE WHEN PROCESSMASTER.COMP_FLG =1 AND PROCESS.MED_PROC_CD='OUT-P' THEN SUM(SUB_PRO.HACYUKIN)
ELSE MAX(SUB_PRO.HACYUKIN)
END) "SUB_TOTAL_PRICE",
--SUM(SUB_PRO.HACYUKIN) "SUB_TOTAL_PRICE",
MAX(SUB_PRO.SICD) "SUB_CODE",
MAX(PROCESSMASTER.PROC_REM) "DE_PROCESS"
FROM T_PLANDATA PLAN
INNER JOIN T_PROCESSNO PROCESSMASTER
ON PLAN.BARCODE = PROCESSMASTER.BARCODE
INNER JOIN T_PLANNED_PROCESS PROCESS
ON PROCESSMASTER.PROCESS_CD = PROCESS.PLAN_PROC_CD
INNER JOIN KEIKAKUMST SUB_PRO
ON PROCESSMASTER.BARCODE = SUB_PRO.KMSEQNO
WHERE PLAN.MFGNO ='T21-F2D1-10034'
GROUP BY PLAN.MFGNO,
PROCESSMASTER.PART_NO,
PROCESS.MED_PROC_CD;
Can we use case SUM and Max in group by function.
Yes
However, your problem is that you use PROCESSMASTER.COMP_FLG =1 AND PROCESS.MED_PROC_CD = 'OUT-P' inside the CASE expression and neither PROCESSMASTER.COMP_FLG nor PROCESS.MED_PROC_CD are in the GROUP BY clause or inside of an aggregation function.
You either want:
SELECT PLAN.MFGNO "MFGNO",
PROCESSMASTER.PART_NO "PART_NO",
PROCESS.MED_PROC_CD "M_PROCESS",
MAX(PLAN.PLAN_START) "PLAN_START_DATE",
MAX(PLAN.PLAN_END) "PLAN_END_DATE",
MAX(PLAN.ACT_START) "ACT_START_DATE",
MAX(PLAN.ACT_END) "ACT_END_DATE",
(CASE WHEN PROCESSMASTER.COMP_FLG =1 AND PROCESS.MED_PROC_CD='OUT-P' THEN SUM(SUB_PRO.HACYUKIN)
ELSE MAX(SUB_PRO.HACYUKIN)
END) "SUB_TOTAL_PRICE",
--SUM(SUB_PRO.HACYUKIN) "SUB_TOTAL_PRICE",
MAX(SUB_PRO.SICD) "SUB_CODE",
MAX(PROCESSMASTER.PROC_REM) "DE_PROCESS"
FROM T_PLANDATA PLAN
INNER JOIN T_PROCESSNO PROCESSMASTER
ON PLAN.BARCODE = PROCESSMASTER.BARCODE
INNER JOIN T_PLANNED_PROCESS PROCESS
ON PROCESSMASTER.PROCESS_CD = PROCESS.PLAN_PROC_CD
INNER JOIN KEIKAKUMST SUB_PRO
ON PROCESSMASTER.BARCODE = SUB_PRO.KMSEQNO
WHERE PLAN.MFGNO ='T21-F2D1-10034'
GROUP BY PLAN.MFGNO,
PROCESSMASTER.PART_NO,
PROCESS.MED_PROC_CD,
PROCESSMASTER.COMP_FLG, -- Add to the group by clause
PROCESS.MED_PROC_CD -- Add to the group by clause
;
or something like:
SELECT PLAN.MFGNO "MFGNO",
PROCESSMASTER.PART_NO "PART_NO",
PROCESS.MED_PROC_CD "M_PROCESS",
MAX(PLAN.PLAN_START) "PLAN_START_DATE",
MAX(PLAN.PLAN_END) "PLAN_END_DATE",
MAX(PLAN.ACT_START) "ACT_START_DATE",
MAX(PLAN.ACT_END) "ACT_END_DATE",
CASE
WHEN MAX(PROCESSMASTER.COMP_FLG) = 1
AND COUNT(CASE WHEN PROCESS.MED_PROC_CD = 'OUT-P' THEN 1 END) > 0
THEN SUM(SUB_PRO.HACYUKIN)
ELSE MAX(SUB_PRO.HACYUKIN)
END "SUB_TOTAL_PRICE",
--SUM(SUB_PRO.HACYUKIN) "SUB_TOTAL_PRICE",
MAX(SUB_PRO.SICD) "SUB_CODE",
MAX(PROCESSMASTER.PROC_REM) "DE_PROCESS"
FROM T_PLANDATA PLAN
INNER JOIN T_PROCESSNO PROCESSMASTER
ON PLAN.BARCODE = PROCESSMASTER.BARCODE
INNER JOIN T_PLANNED_PROCESS PROCESS
ON PROCESSMASTER.PROCESS_CD = PROCESS.PLAN_PROC_CD
INNER JOIN KEIKAKUMST SUB_PRO
ON PROCESSMASTER.BARCODE = SUB_PRO.KMSEQNO
WHERE PLAN.MFGNO ='T21-F2D1-10034'
GROUP BY PLAN.MFGNO,
PROCESSMASTER.PART_NO,
PROCESS.MED_PROC_CD;
Note: this is untested as you have not provided a minimal representative example of your tables or data to test against.

Get the sum of a count column in SQL

I have the following query
SELECT
dtc.coupon_type_company_name,
COUNT(*) * dtc.coupon_type_company_coupon_amount AS 'Total_Coupon_To_Be_Used',
dtc.coupon_type_company_coupon_months_combinable
FROM
[dbo].[coupon_type_Company_User] dtcu
JOIN
coupon_type_Company dtc ON dtcu.coupon_type_Company_ID = dtc.id
JOIN
person p ON dtcu.userID = p.userID
WHERE
coupon_type_company_coupon_is_combinable = 1
OR coupon_type_company_has_coupon = 1
AND dtc.companyID = 1081
AND p.is_active = 1
GROUP BY
dtc.coupon_type_company_name,dtc.coupon_type_company_coupon_amount,
dtc.coupon_type_company_coupon_months_combinable
This returns the following:
What I want to have however is just one column and one row that should take the SUM of my middle column (count(*)*dtc.coupon_type_company_coupon_amount).
How could I achieve this and prevent doing this in my code backend (C#)
You can wrap your query like this:
SELECT SUM(Total_Coupon_To_Be_Used) AS the_sum
FROM (
your query
) s
Use a "Table Expression", as in:
select sum(Total_Coupon_To_Be_Used) from (
SELECT dtc.coupon_type_company_name,
count(*) * dtc.coupon_type_company_coupon_amount as 'Total_Coupon_To_Be_Used',
dtc.coupon_type_company_coupon_months_combinable
FROM [dbo].[coupon_type_Company_User] dtcu
JOIN coupon_type_Company dtc ON dtcu.coupon_type_Company_ID = dtc.id
JOIN person p ON dtcu.userID = p.userID
WHERE coupon_type_company_coupon_is_combinable = 1
or coupon_type_company_has_coupon = 1
and dtc.companyID = 1081
AND p.is_active = 1
GROUP BY
dtc.coupon_type_company_name,dtc.coupon_type_company_coupon_amount,
dtc.coupon_type_company_coupon_months_combinable
) x

Return a Count of 0 When No Rows

OK, I've looked this up and tried a number of solutions, but can't get it to work. I'm a bit of a novice. Here's my original query - how can I get it to return 0 for an account when there are no results in the student table?
SELECT a.NAME
,count(s.student_sid)
FROM account a
JOIN inst i ON a.inst_sid = i.root_inst_sid
JOIN inst_year iy ON i.inst_sid = iy.inst_sid
JOIN student s ON iy.inst_year_sid = s.inst_year_sid
WHERE s.demo = 0
AND s.STATE = 1
AND i.STATE = 1
AND iy.year_sid = 16
AND a.account_sid IN (
20187987
,20188576
,20188755
,52317128
,20189249
)
GROUP BY a.NAME;
Use an outer join, moving the condition on that table into the join:
select a.name, count(s.student_sid)
from account a
join inst i on a.inst_sid = i.root_inst_sid
join inst_year iy on i.inst_sid = iy.inst_sid
left join student s on iy.inst_year_sid = s.inst_year_sid
and s.demo = 0
and s.state = 1
where i.state = 1
and iy.year_sid = 16
and a.account_sid in (20187987, 20188576, 20188755, 52317128, 20189249)
group by a.name;
count() does not count null values, which s.student_sid will be if no rows join from student.
You need to LEFT JOIN and then SUM() over the group where s.student_sid is not null:
select
a.name,
sum(case when s.student_sid is null then 0 else 1 end) as student_count
from account a
join inst i on a.inst_sid = i.root_inst_sid
join inst_year iy on i.inst_sid = iy.inst_sid
left join student s
on iy.inst_year_sid = s.inst_year_sid
and s.demo = 0
and s.state = 1
where i.state = 1
and iy.year_sid = 16
and a.account_sid in (20187987, 20188576, 20188755, 52317128, 20189249)
group by a.name;
This is assuming that all of the fields in the student table that you are filtering on are optional. If you don't want to enforce removal of records where, say, s.state does not equal 1, then you need to move the s.state=1 predicate into the WHERE clauses.
If, for some reason, you are getting duplicate student IDs and students are being counted twice, then you can change the aggregate function to this:
count(distinct s.student_id) as student_count
...which is safe to do as count(distinct ...) ignores null values.

How can I refactor this query

How can I rewrite this SQL code? I would like to avoid the repetitive execution of the case for every record.
SELECT chcr.chsid,
CASE
WHEN EXISTS
(SELECT 1
FROM hdr_run chre,
clmerr ce
WHERE chre.chsid = chcr.chsid
AND chre.run_nmbr < chcr.last_run_nmbr
AND chre.clm_error_sid = ce.clm_error_sid
GROUP BY chre.chsid
HAVING COUNT(chre.clm_error_sid) > 0
)
THEN 'Appended'
ELSE 'Never Appended'
END Run_Detail
FROM
clm_res chcr,
clm_der chde
WHERE chde.chsid = chcr.chsid
Have a look at that query please:
SELECT
chcr.chsid,
CASE
WHEN ce.clm_error_sid IS NOT NULL AND COUNT(chre.clm_error_sid, 0) > 0
THEN 'Appended'
ELSE 'Never Appended'
END Run_Detail
FROM
clm_res chcr
JOIN clm_der chde ON chde.chsid = chcr.chsid
LEFT JOIN hdr_run chre ON chre.chsid = chcr.chsid AND chre.run_nmbr < chcr.last_run_nmbr
LEFT JOIN clmerr ce ON chre.clm_error_sid = ce.clm_error_sid
GROUP BY chcr.chsid
If there's more than one clm_der for each clm_res based on their chsid, we'd have to double check that the COUNT is not counting the extras from clm_der.
I have no data to test this on so all I can go on is the SQL you've provided but from a brief look it does not appear that the GROUP BY and HAVING COUNT() > 0 statements are required as the combination of the INNER JOIN condition in the sub-query and the use of EXISTS in the outer query does the same thing.
Does this have exactly the same functionality:
SELECT chcr.chsid,
CASE
WHEN EXISTS
( SELECT 1
FROM hdr_run chre
INNER JOIN
clmerr ce
ON (chre.clm_error_sid = ce.clm_error_sid)
WHERE chre.chsid = chcr.chsid
AND chre.run_nmbr < chcr.last_run_nmbr
)
THEN 'Appended'
ELSE 'Never Appended'
END Run_Detail
FROM clm_res chcr
INNER JOIN
clm_der chde
ON ( chde.chsid = chcr.chsid );
SQLFIDDLE
Also, repeated execution of the CASE statement is not a bad thing as the optimizer should not duplicate executions of the sub-query.

SQL Server query with CASE and GROUP BY, field invalid?

Can't figure out what I'm doing wrong here. It says field HasNoteDate is invalid. I just want it to return 1 if there's a date, 0 if there's not and I wanted it grouped so I can get the counts and the sum of loan amounts. I've looked at the stackoverflow answers for grouping by a case and none of them are solving it for me. Thanks!
SELECT dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION, COUNT(*) AS TierRegionCount,
SUM(dbo.LOAN.LOAN_AMT) AS LoanAmtSum, dbo.LOAN.DEAL_STATUS, CASE WHEN dbo.WORKFLOW.NOTE_DATE IS NULL
THEN 0 ELSE 1 END AS HasNoteDate
FROM dbo.BRKRMAST INNER JOIN
dbo.BRKRREF ON dbo.BRKRMAST.BRKRMASTID = dbo.BRKRREF.BRKRMASTID INNER JOIN
dbo.LOAN ON dbo.BRKRREF.LoanId = dbo.LOAN.LoanId INNER JOIN
dbo.WORKFLOW ON dbo.LOAN.LoanId = dbo.WORKFLOW.LoanId LEFT OUTER JOIN
dbo.BDONAMES ON dbo.BRKRMAST.BDONAMESID = dbo.BDONAMES.BDONAMESID
WHERE (LEN(dbo.BDONAMES.UserID) > 0) AND (dbo.BRKRMAST.Tier > 0) AND (LEN(dbo.BDONAMES.REGION) > 0)
GROUP BY dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION, dbo.LOAN.LOAN_AMT, dbo.LOAN.DEAL_STATUS, HasNoteDate
ORDER BY dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION
logic of SQL query execution is not straightforward as common programming languages
here are sample execution stages for your query:
perform join on tables in FROM CLAUSE
perform GROUP BY - this will cause error, as HasNoteDate is not defined for this moment
perform ORDER BY
perform SELECT - only during this stage column HasNoteDate is defined
so, you cannot use undefined column HasNoteDate in GROUP BY, you have to replace it with your statement (CASE WHEN dbo.WORKFLOW.NOTE_DATE IS NULL THEN 0 ELSE 1 END), then sql server will be able to GROUP
SELECT dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION, COUNT(*) AS TierRegionCount,
SUM(dbo.LOAN.LOAN_AMT) AS LoanAmtSum, dbo.LOAN.DEAL_STATUS, CASE WHEN dbo.WORKFLOW.NOTE_DATE IS NULL
THEN 0 ELSE 1 END AS HasNoteDate
FROM dbo.BRKRMAST INNER JOIN
dbo.BRKRREF ON dbo.BRKRMAST.BRKRMASTID = dbo.BRKRREF.BRKRMASTID INNER JOIN
dbo.LOAN ON dbo.BRKRREF.LoanId = dbo.LOAN.LoanId INNER JOIN
dbo.WORKFLOW ON dbo.LOAN.LoanId = dbo.WORKFLOW.LoanId LEFT OUTER JOIN
dbo.BDONAMES ON dbo.BRKRMAST.BDONAMESID = dbo.BDONAMES.BDONAMESID
WHERE (LEN(dbo.BDONAMES.UserID) > 0) AND (dbo.BRKRMAST.Tier > 0) AND (LEN(dbo.BDONAMES.REGION) > 0)
GROUP BY dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION, dbo.LOAN.DEAL_STATUS, CASE WHEN dbo.WORKFLOW.NOTE_DATE IS NULL
THEN 0 ELSE 1 END
ORDER BY dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION
Use columns in your group by exactly the way you have defined in you select Statement, otherwise SQL server tries to GROUP it with the fields that it cannot find in SELECT statement and throws an error.