Modify Select Statement To Sum Single Field - sql

I have the below select statement that has extracted all the data I need, but I am trying to modify it so that the REJECTS by SHIFT by PROD_DATE are summed.
SELECT B.PROD_DATE,B.SHIFT,B.REJECTS
FROM REJECTS B
LEFT OUTER JOIN HIST_ILLUM_PART C ON B.HIST_ILLUM_PART_ID = C.ID
LEFT OUTER JOIN HIST_ILLUM_RT A ON A.ID = C.HIST_ILLUM_RT_ID
WHERE
B. REJECT_CODE NOT in ('START','SETUP','QC')
AND B.PROD_DATE >= SYSDATE - 8
ORDER BY SHIFT, PROD_DATE
I have tried
SELECT B.PROD_DATE,B.SHIFT,SUM(B.REJECTS)
I recieve the following error: ORA-00937: not a single-group group function
Do I need a subquery?

Add a GROUP BY clause to your query when doing aggregations. In pseudocode it means for each distinct group of B.PROD_DATE and B.SHIFT get the sum of all B.REJECTS for that set,
SELECT B.PROD_DATE,B.SHIFT,SUM(B.REJECTS) AS REJECTS
FROM REJECTS B
LEFT OUTER JOIN HIST_ILLUM_PART C ON B.HIST_ILLUM_PART_ID = C.ID
LEFT OUTER JOIN HIST_ILLUM_RT A ON A.ID = C.HIST_ILLUM_RT_ID
WHERE
B. REJECT_CODE NOT in ('START','SETUP','QC')
AND B.PROD_DATE >= SYSDATE - 8
GROUP BY B.PROD_DATE,B.SHIFT
ORDER BY SHIFT, PROD_DATE

Related

distinct and sum in single join query

I have the following join query.. I want records to be distinct with c.checkid and also sum of earnings.. how can I perform both in one single query?
select c.CheckID,cv.CheckID,Earnings,TaxableEarnings,Amount,EmployeeCode, CheckDate FROM [Customers0].[pay].[CheckVendorCalc] as cv
inner join [Customers0].[pay].[Checks] as c
on cv.checkid=c.checkid
where
c.CheckDate BETWEEN '2022-01-01' AND '2022-12-31' and
c.CustomerID=360 and
c.EmployeeCode='01' and
(cv.TaxableEarnings !=null or cv.TaxableEarnings!=0)
You can use GROUP BY. Any non-aggregated columns in the SELECT clause must be present in the GROUP BY clause. You can find more information here.
SQL:
select
c.CheckID,
SUM(Earnings) as totalearning
FROM
[Customers0].[pay].[CheckVendorCalc] as cv
inner join [Customers0].[pay].[Checks] as c on cv.checkid = c.checkid
where
c.CheckDate BETWEEN '2022-01-01'
AND '2022-12-31'
and c.CustomerID = 360
and c.EmployeeCode = '01'
and (
cv.TaxableEarnings != null
or cv.TaxableEarnings != 0)
group by
c.CheckID
order by
c.CheckID

Replace correlated subquery with CTE and JOIN

I am trying to rewrite a query which has a correlated subquery, the idea is to replace it with a CTE and join it later.
I have three tables, tbl_transaction, tbl_beneficiaries and tbl_reg_countries. The current (in short) SQL looks like the following.
SELECT
t.USER_ID,
t.TRANSACTION
FROM tbl_transactions t
JOIN tbl_beneficiaries b ON b.ID = t.USER_ID
WHERE b.COUNTRY NOT IN (
SELECT rc.country
FROM tbl_reg_countries rc
WHERE rc.id = t.USER.ID)
My goal is to query only those transactions for each user where the transaction happens outside of the registered countries. So a user may registered X,Y,Z country but had business with Q. In that case only Q should be returned. How could this be replaced with a CTE/JOIN?
I assume both tbl_beneficiaries.COUNTRY and tbl_reg_countries.COUNTRY are not nullable. You can use a LEFT JOIN with NULL test to detect never matching rows
SELECT
t.USER_ID,
t.TRANSACTION
FROM tbl_transactions t
JOIN tbl_beneficiaries b ON b.ID = t.USER_ID
LEFT JOIN tbl_reg_countries rc ON rc.id = t.USER_ID AND b.COUNTRY = rc.country
WHERE rc.country IS NULL
I would try rewriting query with "with"
Like this:
With a As
(Select
Distinct rc.country
From tbl_reg_countries rc
Inner Join tbl_transactions t on rc.id = t.USER.ID
)
Select
t.USER_ID,
t.TRANSACTION
From tbl_transactions t
Inner Join tbl_beneficiaries b On b.ID = t.USER_ID
Where b.COUNTRY Not In (select * from a)

Group by count zero rows not displaying

I want to count the amount of rows of every componistId. When I run the following SQL statement it works fine:
SELECT C.componistId, COUNT(*)
FROM Componist C LEFT JOIN Stuk S ON S.componistId = C.componistId
GROUP BY C.componistId
Now I want only the rows where stukNrOrigineel is null
SELECT C.componistId, COUNT(*)
FROM Componist C LEFT JOIN Stuk S ON S.componistId = C.componistId
WHERE S.stuknrOrigineel IS NULL
GROUP BY C.componistId
But when I do this, all the rows with a result of 0 disappear. Only the rows with at least 1 row are displayed. How can I make this work?
You need to include the condition in the on clause:
SELECT C.componistId, COUNT(C.componistId)
FROM Componist C LEFT JOIN
Stuk S
ON S.componistId = C.componistId AND
S.stuknrOrigineel IS NULL
GROUP BY C.componistId;
Note: I changed the COUNT() to count from the second table. This is normally what you want when combining LEFT JOIN with COUNT().
On some databases, I think the above might not quite work as expected (the question is whether the condition on S is evaluated before or after the LEFT JOIN). This should always work:
SELECT C.componistId, COUNT(s.componistId)
FROM Componist C LEFT JOIN
(SELECT S.* FROM Stuk S WHERE S.stuknrOrigineel IS NULL
) s
ON S.componistId = C.componistId AND
GROUP BY C.componistId;
Another generic solution is move the condition into the aggregation function:
SELECT C.componistId,
SUM(CASE WHEN S.stuknrOrigineel IS NULL THEN 1 ELSE 0 END)
FROM Componist C LEFT JOIN
Stuk S
ON S.componistId = C.componistId
GROUP BY C.componistId;

Subquery Where clause invalid in select list

I am trying to create a numerator(num) and denominator(den) column that I will later use to create a metric value. In my numerator column, I need to have a criteria that my denominator column does not have. When I add the where clause to my sub query, I am getting the error below. I do not want to add INRInRange to my Group By clause.
Column 'dbo.PersonDetailB.INRInRange' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause."
SELECT
dbo.PersonDetailSpecialty.PracticeAbbrevName,
(SELECT COUNT(DISTINCT dbo.Problem.PID) WHERE PersonDetailB.INRInRange='True') AS num,
COUNT(DISTINCT dbo.Problem.PID) AS den
FROM
dbo.PersonDetailB
RIGHT OUTER JOIN
dbo.PersonDetailSpecialty ON dbo.PersonDetailB.PID = dbo.PersonDetailSpecialty.PID
LEFT OUTER JOIN
dbo.Problem ON dbo.PersonDetailSpecialty.PID = dbo.Problem.PID
GROUP BY
practiceabbrevname
Create a sub-query that counts PersonDetailB.INRInRange and LEFT OUTER JOIN it with the original query.
SELECT Main.PracticeAbbrevName, InRange.Num AS num, Main.den
FROM
(SELECT
dbo.PersonDetailSpecialty.PracticeAbbrevName,
COUNT(DISTINCT dbo.Problem.PID) AS den
FROM
dbo.PersonDetailB
RIGHT OUTER JOIN
dbo.PersonDetailSpecialty ON dbo.PersonDetailB.PID = dbo.PersonDetailSpecialty.PID
LEFT OUTER JOIN
dbo.Problem ON dbo.PersonDetailSpecialty.PID = dbo.Problem.PID
GROUP BY
practiceabbrevname) Main
LEFT OUTER JOIN
(SELECT practiceabbrevname, COUNT(DISTINCT dbo.Problem.PID) Num WHERE PersonDetailB.INRInRange='True' GROUP BY practiceabbrevname) InRange ON Main.practiceabbrevname = InRange.practiceabbrevname
The problem with this statement:
SELECT dbo.PersonDetailSpecialty.PracticeAbbrevName,
(SELECT COUNT(DISTINCT dbo.Problem.PID) WHERE PersonDetailB.INRInRange = 'True') AS num,
COUNT(DISTINCT dbo.Problem.PID) AS den
is that PersonDetailB.INRInRange1 doesn't have a unique value in each group. It is possible that it does. One method is to add it to the GROUP BY:
GROUP BY practiceabbrevname, PersonDetailB.INRInRange
Another method would use an aggregation function in the subquery:
SELECT dbo.PersonDetailSpecialty.PracticeAbbrevName,
(SELECT COUNT(DISTINCT dbo.Problem.PID) WHERE MAX(PersonDetailB.INRInRange) = 'True') AS num,
COUNT(DISTINCT dbo.Problem.PID) AS den
Join a separate table as a different name on the where criteria that was in the sub query.
SELECT PersonDetailSpecialty.PracticeAbbrevName,
COUNT(PDTRUE.PID) as num,
COUNT(dbo.Problem.PID) AS den
FROM dbo.PersonDetailSpecialty LEFT OUTER JOIN
dbo.PersonDetailB as PDTRUE ON dbo.PersonDetailSpecialty.PID = PDTRUE.PID and PDTRUE.INRInRange='True' LEFT OUTER JOIN
dbo.PersonDetailB ON dbo.PersonDetailSpecialty.PID = PersonDetailB.PID LEFT OUTER JOIN
dbo.Medicate ON dbo.PersonDetailSpecialty.PID = dbo.Medicate.PID LEFT OUTER JOIN
dbo.Problem ON dbo.PersonDetailSpecialty.PID = dbo.Problem.PID
GROUP BY PersonDetailSpecialty.PracticeAbbrevName
This is the relevant code needed in the FROM section
dbo.PersonDetailSpecialty LEFT OUTER JOIN dbo.PersonDetailB as PDTRUE
ON dbo.PersonDetailSpecialty.PID = PDTRUE.PID and PDTRUE.INRInRange='True'
This lets you add
COUNT(PDTRUE.PID) as num,
as a simple part of the overall select query

An error : Subquery returned more than 1 value

I am getting the error-msg when i try the following code:
SELECT COUNT(*) FROM [ServerName].[dbo].[TableName1] B
WHERE right(B.TableName1, 2) = '34' AND
B.UnitId=
(select distinct D.UnitId
from [ServerName].[dbo].[TableName2] D
INNER JOIN #temp E ON D.UnitId=E.UnitId)
Does anyone know how to solve it? It says the subquery returned more than 1 value. The temp-table is created and contains a selection of the number individuals that I want to count, by unitId.
Try using a join instead of the subquery:
SELECT COUNT(*)
FROM [ServerName].[dbo].[TableName1] B
INNER JOIN [ServerName].[dbo].[TableName2] D ON B.UnitId = D.UnitId
INNER JOIN #temp E ON D.UnitId = E.UnitId
WHERE RIGHT(B.TableName1, 2) = '34'
The subquery (select distinct) has more than one value returned. As such B.UnitId cannot equal more than one value.
You can use IN if its ok for B.UnitId to have more than one value.
SELECT COUNT(*)
FROM [ServerName].[dbo].[TableName1] B
WHERE right(B.TableName1, 2) = '34'
AND B.UnitId in (select D.UnitId
from [ServerName].[dbo].[TableName2] D
INNER JOIN #temp E ON D.UnitId=E.UnitId)
Distinct becomes superfluous when you use IN.