Query correctly returns calculations but returns null when multiplied together in a sum - sql

I am trying to calculate the sum of two calculations multiplied together. Independently, the {Hours} and {Rate} calculations work just fine but when I multiply them together within a sum formula, they normally return a null. The exception is that they will return 0 if the rate is 0.
If anyone has an guidance, it would be appreciated. I would also love to know what I did wrong because I'm teaching myself this.
Select
SFLTX.BF2RDAT as {Date},
SFLTX.BF2DEPT as {Dept},
sum((SFLTX.BF2QTYG / HJOBDR.EDRUNS)) as {HOURS},
(RESRE.ABLABR * ((RESRE.ABBRDP + RESRE.ABBDVP)/100)) as {RATE},
sum((SFLTX.BF2QTYG / HJOBDR.EDRUNS) * (RESRE.ABLABR * ((RESRE.ABBRDP + RESRE.ABBDVP)/100))) as {ABS}
from SFLTX
join ERW.FCALPF on SFLTX.BF2RDAT = ERW.FCALPF.FDATE
join HJOBDR on SFLTX.BF2JOBN = HJOBDR.EDJOB# and SFLTX.BF2SEQN = HJOBDR.EDSEQ#
Join RESRE on SFLTX.BF2DEPT = RESRE.ABDEPT and SFLTX.BF2RESC = RESRE.ABRESC
where SFLTX.BF2RDAT > '1/1/2019' and (right(ERW.FCALPF.FYEAR,2) = ‘19’ and SFLTX.BF2CMODE = 'R')
group by SFLTX.BF2RDAT , SFLTX.BF2DEPT, (RESRE.ABLABR * ((RESRE.ABBRDP + RESRE.ABBDVP)/100))
I attached an image of the data output.

If any of the columns involved in any of the calculations contains NULL values, then the result of the calculation will likewise be NULL. Ensure that either all columns are defined as NOT NULL, or, use a CASE statement to convert any NULL value to 0 or 0.00 (unless you are going to be dividing by that column).

Related

SQL integer division returns 0 rows

I am trying to create a calculated field called efficiency %. This is calculated by taking LaborDtl.LaborHrs minus Calculated_Shouldhavetaken divided by Calculated_Shouldhavetaken. When I run the query I get zero rows returned, but creating the calculated field without the division returns the difference as expected. I believe this is due to how division is treated in the server.
/*
* Disclaimer!!!
* This is not a real query being executed, but a simplified version for general vision.
* Executing it with any other tool may produce a different result.
*/
select
[LaborDtl].[JobNum] as [LaborDtl_JobNum],
[JobHead].[PartNum] as [JobHead_PartNum],
[LaborDtl].[EmployeeNum] as [LaborDtl_EmployeeNum],
[LaborDtl].[OpCode] as [LaborDtl_OpCode],
[JobHead].[ProdQty] as [JobHead_ProdQty],
(LaborDtl.LaborQty + LaborDtl.ScrapQty) as [Calculated_TotalQty],
[LaborDtl].[LaborHrs] as [LaborDtl_LaborHrs],
(TotalQty/ JobHead.ProdQty* LaborDtl.LaborHrs* 1.0) as [Calculated_Shouldhavetaken],
[LaborDtl].[ClockInDate] as [LaborDtl_ClockInDate],
((LaborDtl.LaborHrs- Shouldhavetaken)/ Shouldhavetaken) as [Calculated_effpercent]
from Erp.LaborDtl as LaborDtl
inner join Erp.JobOper as JobOper on
LaborDtl.Company = JobOper.Company
and LaborDtl.JobNum = JobOper.JobNum
and LaborDtl.AssemblySeq = JobOper.AssemblySeq
and LaborDtl.OprSeq = JobOper.OprSeq
inner join Erp.JobOpDtl as JobOpDtl on
JobOper.Company = JobOpDtl.Company
and JobOper.JobNum = JobOpDtl.JobNum
and JobOper.AssemblySeq = JobOpDtl.AssemblySeq
and JobOper.OprSeq = JobOpDtl.OprSeq
inner join Erp.JobHead as JobHead on
JobOpDtl.Company = JobHead.Company
and JobOpDtl.JobNum = JobHead.JobNum
where (LaborDtl.ClockInDate = dateadd (day, -1, Constants.Today))
Any guidance would be appreciated.
Thanks
It could be as you mentioned. Any chance you could encapsulate the query and do your calculation for the division part outside just to test it?
Try casting decimal around Shouldhavetaken
CAST(Shouldhavetaken AS DECIMAL(9,2))
or something like that. See if works.
Another test you can run is to hardcode an int as the divisor and hardcode a decimal and see if you get different results. / 2 or / 2.0

Returns the percent column as the value 1 all over. How do I fix it?

I want to create a view that calculates percentage, but what I have done, it only returns the percent column as the value 1 all over. How do I fix it?
GO
CREATE VIEW vRejectedProductsByType AS
SELECT
DimProductType.ProductTypeName,
DimProductSubtype.ProductSubtypeName,
CONVERT(DECIMAL(5,4), ManufacturingFact.RejectedProducts * 100 / (ManufacturingFact.AcceptedProducts + ManufacturingFact.RejectedProducts)) AS PercentRejected,
CONVERT(INT, ManufacturingFact.AcceptedProducts + ManufacturingFact.RejectedProducts) AS TotalManufactured,
CONVERT(DATE, ManufacturingFact.DateOfManufacture) AS DateOfManufacture
FROM DimProduct
INNER JOIN DimProductSubtype
ON DimProduct.ProductSubtypeCode = DimProductSubtype.ProductSubtypeCode
INNER JOIN DimProductType
ON DimProductType.ProductTypeCode = DimProductSubtype.ProductTypeCode
INNER JOIN ManufacturingFact
ON DimProduct.ProductCode = ManufacturingFact.ProductCode;
GO
As others commented, here is the result. First, your long table names make for more difficult readability. By using alias names that closer match the table source, it becomes easier to read. For example DimProduct now has an alias "dp". DimProductSubType is "st" (for sub type), similar with t=type, mf=manufacturing fact.
Now, you had all those converts. If the data types are already integer, no need to convert an int to an int.
As for the date, that would be the only one that I MIGHT keep the convert( date, ) context IF that column were based on a date/time inclusive and you only wanted to see the date itself, otherwise, just leave the date alone.
Your percentage calculation, since you were dividing int by an int, it gave you an int. To fix, just turn one into a decimal or float as noted by multiplying by 100.0
SELECT
t.ProductTypeName,
st.ProductSubtypeName,
mf.RejectedProducts * 100.0 / (mf.AcceptedProducts + mf.RejectedProducts) PercentRejected,
mf.AcceptedProducts + mf.RejectedProducts TotalManufactured,
mf.DateOfManufacture
FROM
DimProduct dp
JOIN DimProductSubtype st
ON dp.ProductSubtypeCode = st.ProductSubtypeCode
JOIN DimProductType t
ON st.ProductTypeCode = t.ProductTypeCode
JOIN ManufacturingFact mf
ON dp.ProductCode = mf.ProductCode;
Finally, to ever see / sample multiplication impacts in the future, you could always just sample from the SQL command window area and do something like
select 37 / 40
vs
select 37.0 / 40
or
select 37 / 40.0
and you can immediately see what SQL is going to do based on the data types.

SQL Server operating with null value

I'm trying to make an average of two columns that may or not contain in the second one Null values. Can someone help me get an idea of how to make an operation between these values?
select
nib, primeiroTitular, segundoTitular,
((YEAR(GETDATE()) - YEAR(P1.dataNascimento)) +
(YEAR(GETDATE()) - YEAR(P2.dataNascimento)))/2 as média
from
ContasBancarias
left join
Pessoas P1 on P1.bi = ContasBancarias.primeiroTitular
left join
Pessoas P2 on P2.bi = ContasBancarias.segundoTitular
Here is what you can do. I changed the way that you do calculation between the two dates I used the DATEDIFF() function Next time try to indent your code when you ask a question it's easier for the people when they try to read your code.
SELECT nib
, primeiroTitular
, segundoTitular
,(DATEDIFF(YEAR,GETDATE(), CASE
WHEN P1.dataNascimento IS NULL
THEN GETDATE()
ELSE P1.dataNascimento
END )
+ DATEDIFF(YEAR,GETDATE(),CASE
WHEN P2.dataNascimento IS NULL
THEN GETDATE()
ELSE P2.dataNascimento
END) )/2 as média
FROM ContasBancarias
LEFT JOIN Pessoas P1
ON P1.bi = ContasBancarias.primeiroTitular
LEFT JOIN Pessoas P2
ON P2.bi = ContasBancarias.segundoTitular
Assuming only the second column could be NULL try this -
([Column1] + ISNULL(Column2,0))/2 AS [Average]
In the interest of accuracy, I would recommend NOT INCLUDING any NULLs in your equation, since NULL means "don't know the value", "don't know what the value is", or "don't know if this value is relevant at all". To assign a zero value to NULL is to skew the results.
Most accurate results, use the WHERE clause to eliminate any row with NULL from the calculations, or the ISNULL function.

Sqlite subquery with multiple sums

I have a sqlite database and I need to perform some arithmetic in my sql to get the final amount. The thing is I am not certain how to go and achieve this, I'm pretty certain from what I've been reading its a subquery which I need to group by lineID (unique id in my db)
The fields I want to include in the calculation below are
el.material_cost1 * el.material_qty1
el.material_cost2 * el.material_qty2
el.material_cost3 * el.material_qty3
The query I currently have is below. It returns the value of my costs apart from the fields missing above. As I store the material costs individually, I can't work out how to do a subquery within my query to get the desired result.
SELECT sum(el.enquiry_cost1) + sum(el.enquiry_cost2) + sum(el.enquiry_cost3)
FROM estimate e
LEFT JOIN estimate_line el
ON e.estimateID=el.estimateID
WHERE e.projectID=7 AND el.optional='false'
Use of a LEFT JOIN instead of an [INNER] JOIN is pointless, as your WHERE condition filters out any rows that could have differed.
I think you're making this harder than it needs to be. In particular, nothing in your description makes me think you need a subquery. Instead, it looks like this query would be close to what you're after:
SELECT
sum(el.enquiry_cost1)
+ sum(el.enquiry_cost2)
+ sum(el.enquiry_cost3)
+ sum(el.material_cost1 * el.material_qty1)
+ sum(el.material_cost2 * el.material_qty2)
+ sum(el.material_cost3 * el.material_qty3)
AS total_costs,
FROM
estimate e
JOIN estimate_line el
ON e.estimateID = el.estimateID
WHERE e.projectID = 7 AND el.optional = 'false'

Using Case Statement to replace value in one field based on value in a seperate field

I'm creating a report in SSRS and I can't use the IIF statement within the report to get the following done. I'm getting aggregate errors when I try to sum within the SSRS report.
`IIF(Fields!Period=0,0,IIF(Period=13,0,Balance/12))`
Works fine up until the moment I try to Sum.. get a silly aggregate error "Aggregate functions other than First, Last, Previous, Count, and Count Distinct can only aggregate data of a single data type"... These are all integers.
Basically I have a value in Master.Balance that I need to divide by 12 only when Secondary.Period equals 0 or 13. If Secondary.Period equals 0 or 13 then the value should be 0. I know my problem has to do with including the relationship between the tables, but I just don't know how to write that in.
Here is what I'm trying to use:
`CASE
WHEN Secondary.Period=0 OR Secondary.Period=13
THEN 0
ELSE Master.Balance/12
End As BudByPer`
Here is how the two tables are related to each other:
`FROM Master LEFT OUTER JOIN Secondary
ON Master.Project = Secondary.Project
AND Master.object = Secondary.object
AND Master.org = Secondary.org
`
How do I get the above into this:
SELECT DISTINCT Master.Project, Master.Object, Master.Fund, Master.Segment, Master.Balance, Secondary.project, Secondary.object, Secondary.org, Secondary.Period, Secondary.object, Secondary.Project.
FROM Master LEFT OUTER JOIN Secondary
ON Master.Project = Secondary.Project
AND Master.object = Secondary.object
AND Master.org = Secondary.org
WHERE (Master.object>=600000)
ORDER BY [Master.Fund]
You just need a select, it looks fine to me...
SELECT
Master.account,
Master.segment,
Secondary.desc,
Secondary.bud,
Segment.Num,
Segment.office,
CASE
WHEN Secondary.Period=0 OR Secondary.Period=13 THEN 0
ELSE Master.Balance/12
End As BudByPer
FROM Master
LEFT JOIN Secondary
ON Master.Project = Secondary.Project
AND Master.object = Secondary.object
AND Master.org = Secondary.org