SQL Division returning odd value - sql

So Basically I have two sum values, that I return. I then divide one of them by the other, my goal was to get spit out a basic value. However the Value that is returned is all over the place.
I assume I screwed up the "Cast" but I am not sure here.
It would be impossible for me to share the entirety of the SQL that generates this. I will focus on the end results here which start with an Outer Apply:
This is me calling the Outer apply values for display, and then my attempt at dividing them:
,VerifyBlock.Numa as [Numerator]
,VerifyBlock.Denominator
,(isNull(((VerifyBlock.Numa) / NullIF(VerifyBlock.Denominator,0)),0)) as [Division]
This is the outer apply that generates the above:
OUTER APPLY (SELECT CASE WHEN CAST(tmpdc2.[14]AS decimal(10,2)) <= 0 AND (CASE WHEN T4MathBlock.[Value] >0 THEN T4MathBlock.[Value]
ELSE '0.00' END)<= 0
THEN '0.00'
ELSE (CASE WHEN CAST(tmpdc2.[14]AS decimal(10,2)) < (CASE WHEN T4MathBlock.[Value] >0 THEN T4MathBlock.[Value]
ELSE '0.00' END) THEN CAST(tmpdc2.[14]AS decimal(10,2))
ELSE (CASE WHEN T4MathBlock.[Value] >0 THEN T4MathBlock.[Value]
ELSE '0.00' END) End)
END AS [Amount]
From ##TempDisclosure tmpdc2
WHERE tmpdc1.[Student Number] = Tmpdc2.[Student Number]
)[AF]
WHERE tmpdc1.[Student Number] = Tmpdc.[Student Number]
)[VerifyBlock]
Sorry if the formatting is wonky.
I know the Values generated by:
VerifyBlock.Numa and VerifyBlock.Denominator are solid. The values they return are
32747682.64 and 78740189.20 (Respectively)
The Division though returns: 947860.602435
When it should actually return: 0.4158954019886963
So where the heck did I go wrong here?

Related

SQL/Oracle issue, I receive this error " REPORTS.WEK_MTD_BILL_SUM_HIST_T.BILL_CYCLE: invalid identifier at line 48" , is there anyway to fix this?

enter image description here
above is the image of the code, my objective is to have 4 columns demonstrating the prices for a bill cycle, and 4 columns demonstrating the average of all bill cycles one year before the initial bill cycle.
the first inner select works by itself and adds the 4 columns to the right in the picture below, the problem starts when I want to add second inner select the 4 columns for yearly average. initially I didn't have the "select * from", but I couldn't find a better way
the base of the problem is that I can't implement 2 Where clauses on the same column.
below is the snap shot of what I get from running only the first inner select.
enter image description here
I have tried union , join, cross join ... but none seem to work, one person suggested "window function" but I haven't worked with that yet.
this is the error below:
enter image description here
RAW CODE TEXT IS BELOW:
VARIABLE START_DATE CHAR
EXEC :START_DATE :=''
VARIABLE END_DATE CHAR
EXEC :END_DATE=''
select * from
(SELECT
"REPORTS"."WEK_MTD_BILL_SUM_HIST_T"."BILL_CYCLE",
"REPORTS"."WEK_MTD_BILL_SUM_HIST_T"."MTD_TOT" AS NET_TOTAL,
SUM(
SUM(
CASE WHEN "REPORTS"."WEK_MTD_BILL_SUM_HIST_T"."BLI_TYPE" = 'Charges'
THEN "WEK_MTD_BILL_SUM_HIST_T"."MTD_TOT" END)) OVER() AS TOTAL_CHARGES,
SUM(
SUM(
CASE WHEN "REPORTS"."WEK_MTD_BILL_SUM_HIST_T"."BLI_TYPE" = 'Credits'
THEN "WEK_MTD_BILL_SUM_HIST_T"."MTD_TOT" END)) OVER() AS TOTAL_CREDIT,
SUM(
SUM(
CASE WHEN "REPORTS"."WEK_MTD_BILL_SUM_HIST_T"."BLI_TYPE" = 'Previous Weekly Billing Net Total'
THEN "WEK_MTD_BILL_SUM_HIST_T"."MTD_TOT" END)) OVER() AS PRV_INVOICED,
SUM(
SUM(
CASE WHEN "REPORTS"."WEK_MTD_BILL_SUM_HIST_T"."BLI_TYPE" = 'Total Due / Receivable'
THEN "WEK_MTD_BILL_SUM_HIST_T"."MTD_TOT"
ELSE 0 END)) OVER() AS Net_Due_Total
FROM "REPORTS"."WEK_MTD_BILL_SUM_HIST_T"),
(SELECT
"REPORTS"."WEK_MTD_BILL_SUM_HIST_T"."BILL_CYCLE",
"REPORTS"."WEK_MTD_BILL_SUM_HIST_T"."MTD_TOT" AS NET_TOTAL,
(SUM(
SUM(
CASE WHEN "REPORTS"."WEK_MTD_BILL_SUM_HIST_T"."BLI_TYPE" = 'Total Due / Receivable' AND ( "REPORTS"."WEK_MTD_BILL_SUM_HIST_T"."BILL_CYCLE" BETWEEN '1-JAN-2022 4' AND :END_DATE)
THEN "WEK_MTD_BILL_SUM_HIST_T"."MTD_TOT" ELSE 0 END)) OVER()/COUNT(DISTINCT(BILL_CYCLE))) AS X
FROM
"REPORTS"."WEK_MTD_BILL_SUM_HIST_T"
WHERE
("REPORTS"."WEK_MTD_BILL_SUM_HIST_T"."BILL_CYCLE" BETWEEN :START_DATE AND :END_DATE )
)
GROUP BY
"REPORTS"."WEK_MTD_BILL_SUM_HIST_T"."MTD_TOT" ,
"REPORTS"."WEK_MTD_BILL_SUM_HIST_T"."BILL_CYCLE"
;

Sum values in two different tables and join results keeping the columns

I have two tables: one with downtime and the other with productive time.
I want to have a table like this
But I am getting this
In the result, I am getting twice the downtime of the sum for the report 04102021-1, but as can be seen in the second picture, the value is present only once.
The script I am using is the following:
SELECT WAJ.REPORTCODE,--BASIC_REPORT_TABLE.TECHNICIAN,BASIC_REPORT_TABLE.JOBREPORTCODE,
SUM(CASE WHEN DATEDIFF(SECOND,WAJ.TIMESTARTED,WAJ.TIMEFINISHED)<0
THEN (86400+DATEDIFF(SECOND,WAJ.TIMESTARTED,WAJ.TIMEFINISHED))/3600.0
ELSE DATEDIFF(SECOND,WAJ.TIMESTARTED,WAJ.TIMEFINISHED) /3600.0
END) AS PRODUCTION_TIME,
SUM(CASE WHEN DATEDIFF(SECOND,WAS.TIMESTARTED,WAS.TIMEFINISHED)<0
THEN (86400+DATEDIFF(SECOND,WAS.TIMESTARTED,WAS.TIMEFINISHED))/3600.0
ELSE DATEDIFF(SECOND,WAS.TIMESTARTED,WAS.TIMEFINISHED) /3600.0
END) AS DOWNTIME
FROM WORK_AT_JOB WAJ,WAITING_AT_SITE WAS
WHERE (WAJ.REPORTCODE=WAS.REPORTCODE AND WAJ.REPORTCODE LIKE '04102021%') GROUP BY WAJ.REPORTCODE
After the #xQbert comment, I tried this:
SELECT WAS.REPORTCODE,
SUM(CASE WHEN DATEDIFF(SECOND,WAJ.TIMESTARTED,WAJ.TIMEFINISHED)<0
THEN (86400+DATEDIFF(SECOND,WAJ.TIMESTARTED,WAJ.TIMEFINISHED))/3600.0
ELSE DATEDIFF(SECOND,WAJ.TIMESTARTED,WAJ.TIMEFINISHED) /3600.0
END) AS PRODUCTION_TIME,
SUM(CASE WHEN DATEDIFF(SECOND,WAS.TIMESTARTED,WAS.TIMEFINISHED)<0
THEN (86400+DATEDIFF(SECOND,WAS.TIMESTARTED,WAS.TIMEFINISHED))/3600.0
ELSE DATEDIFF(SECOND,WAS.TIMESTARTED,WAS.TIMEFINISHED) /3600.0
END) AS DOWNTIME
FROM WAITING_AT_SITE WAS
JOIN WORK_AT_JOB WAJ
ON (WAJ.REPORTCODE=WAS.REPORTCODE AND WAS.REPORTCODE LIKE '04102021%') GROUP BY WAS.REPORTCODE
But I got the same result.
May you give some advice to get the result I want?
Thanks in advance
You could use conditional aggregation for this, but the easiest, and probably most performant, way to do this is to pre-aggregate the results before you join.
SELECT
waj.REPORTCODE
waj.PRODUCTION_TIME,
was.DOWNTIME
FROM (
SELECT
waj.REPORTCODE,
SUM(CASE WHEN v.diff < 0 THEN 86400 + v.diff ELSE v.diff END / 3600.0) AS PRODUCTION_TIME
FROM WORK_AT_JOB waj
CROSS APPLY (VALUES( DATEDIFF(SECOND, waj.TIMESTARTED, waj.TIMEFINISHED) )) v(diff)
WHERE waj.REPORTCODE LIKE '04102021%'
GROUP BY
waj.REPORTCODE
) waj
JOIN (
SELECT
was.REPORTCODE,
SUM(CASE WHEN v.diff < 0 THEN 86400 + v.diff ELSE v.diff END / 3600.0) AS PRODUCTION_TIME
FROM WAITING_AT_SITE was
CROSS APPLY (VALUES( DATEDIFF(SECOND, was.TIMESTARTED, was.TIMEFINISHED) )) v(diff)
WHERE was.REPORTCODE LIKE '04102021%'
GROUP BY
was.REPORTCODE
) was ON waj.REPORTCODE = was.REPORTCODE;
Note the use of CROSS APPLY (VALUES to avoid code repetition.

SQL server View - loop help (while loop)

I've been asked to produce a dataset using a view in SQL and have a number of products (eg 'a a','b b','c c') and I want to work out totals over 5 years (1,2,3,4,5) and output the totals as total_a_a_yr1, total_b_b_yr1....(see the below code)
Rather than writing out loads of lines of code is there a more efficient way of coding?
I thought about creating a procedure but I don't think you can use an EXEC within a view. I may be wrong. A while loop might be the way to go but I'm unsure about using declares in views.
Any help would be appreciated. Thanks
,sum(case when product = 'a a' and floor(datediff(dd, date1,date2)/365.25)<1
then amount_received else null end) as total_a_a_yr1
,sum(case when product = 'a a' and floor(datediff(dd, date1,date2)/365.25)<(2)
then amount_received else null end) as total_a_a_yr2
,sum(case when product = 'a a' and floor(datediff(dd, date1,date2)/365.25)<(3)
then amount_received else null end) as total_a_a_yr3
,sum(case when product = 'a a' and floor(datediff(dd, date1,date2)/365.25)<(4)
then amount_received else null end) as total_a_a_yr4
,sum(case when product = 'a a' and floor(datediff(dd, date1,date2/365.25)<(5)
then amount_received else null end) as total_a_a_yr5
First, the default value for a case statement is NULL so, "ELSE NULL" is not necessary. Second, this formula is probably not doing exactly what you think: floor(datediff(dd, date1,date2)/365.25). What I mean is, if you are operating under the assumption that there is a leap year every four years, you are incorrect. Leap years don't happen on years divisible by 100 UNLESS it can also be divided by 400. I could be misunderstanding what you're trying to do however.
You're correct, You can't use dynamic SQL (e.g. EXEC '<sql code>') in a view. There's very little you can't do with a tally table. Here's how you'd generate your code programatically using a tally table (I'm going to 1 to 100):
with yourExpression(ex) as
(
select ',sum(case when product = ''''a a'''' and floor(datediff(dd, date1,date2)/365.25)<
then amount_received else null end) as total_a_a_yr'
),
iTally(N) as
(
select top(100) cast(row_number() over (order by (select null)) as varchar(3))
from sys.all_columns
)
select stuff(ex,78,0,'('+N+')')+N
from iTally
cross join yourExpression;
You can copy/paste and execute the query as is; it will return:
,sum(case when product = ''a a'' and floor(datediff(dd, date1,date2)/365.25)<(1)
then amount_received else null end) as total_a_a_yr1
,sum(case when product = ''a a'' and floor(datediff(dd, date1,date2)/365.25)<(2)
then amount_received else null end) as total_a_a_yr2
,sum(case when product = ''a a'' and floor(datediff(dd, date1,date2)/365.25)<(3)....
--<truncated for brevity> ... as total_a_a_yr100

Possible to do math inside of a sum statement?

I'm by no means an expert in DB2 so apologies if this is a novice question. I am looking for a specific requirement. I am summing through a table based on a case statement but am wondering if we could subtract an amount if a field is present in the row.
SELECT CODE,
SUM(CASE SUBSTR(DATE,4,2)
WHEN '01' THEN AMT
END) as JanuaryTotal
FROM Table1
I'm looking to see if we can simply, if another field is present, if we can instead of summing it, simply subtract it from the total that is currently in place.
SELECT CODE,
SUM(CASE SUBSTR(DATE,4,2)
WHEN '01' THEN CASE WHEN TYPE = 'X'
THEN - AMT // some possible way to do this?
ELSE AMT
END) as JanuaryTotal
FROM Table1
Again, apologies. i know this code doesnt run but just giving a visual of something to see if it's possible to do.
SELECT CODE, SUM(
CASE
WHEN SUBSTR(DATE,4,2) = '01' THEN AMT
WHEN TYPE = 'X' THEN 0 - AMT
ELSE AMT
END
) as JanuaryTotal
FROM Table1
Sometimes it helps to indent. Also, it is not quite clear what to do if the sub-string is not 01 -- I'm guessing you don't want to add anything.
SELECT CODE,
SUM(CASE SUBSTR(DATE,4,2)
WHEN '01' THEN
CASE
WHEN TYPE = 'X' THEN -1 * AMT
ELSE AMT
END
ELSE 0 -- SUBSTR(DATE,4,2) is not '01'
END) as JanuaryTotal
FROM Table1
The simplest final query is to flatten out your conditions so they stand alone:
SELECT CODE, SUM(CASE
WHEN SUBSTR(DATE,4,2) AND TYPE = 'X' THEN 0-AMT
WHEN SUBSTR(DATE,4,2) AND THEN AMT END) as JanuaryTotal
FROM Table1
Note that there are two forms of CASE:
CASE <expression>
WHEN <value> THEN ...
WHEN <value> THEN ...
and
CASE
WHEN <condition> THEN ...
WHEN <condition> THEN ...
I switched your query from using the first form to the second form.
SELECT CODE, SUM(
CASE
WHEN SUBSTR(DATE,4,2) = '01' and TYPE = 'X' THEN -AMT
else AMT
END
) as JanuaryTotal
FROM Table1
group by CODE

MySQL using calculated return values to calculate other values

Let's say I have a select Statement with the following:
SUM(st.tafPoints/200) as totalFriendReferrals,
SUM(CASE WHEN st.gender = "m" THEN st.tafPoints/200 ELSE 0 END) as maleFriendReferrals,
SUM(CASE WHEN st.gender = "f" THEN st.tafPoints/200 ELSE 0 END) as femaleFriendReferrals
I need to calculate the percentage of maleFriendReferrals based on the totalFriendReferrals. These are both derived (ie, not originally in the list of columns) values. So if I try to do something like:
CONCAT( (maleFriendReferrals/totalFriendReferrals) *100 , '%') as malePercentReferrals
But I get an error:
Unknown column 'maleFriendReferrals' in 'field list' – 1 ms
Is there a way to do this easily? I need to be able to do this within the query itself, and not have to loop through my results to calculate percentages.
You should put the original query to a subquery
SELECT CONCAT( (maleFriendReferrals/totalFriendReferrals) *100 , '%') as malePercentReferrals
FROM
(SELECT
SUM(st.tafPoints/200) as totalFriendReferrals,
SUM(CASE WHEN st.gender = "m" THEN st.tafPoints/200 ELSE 0 END) as maleFriendReferrals,
SUM(CASE WHEN st.gender = "f" THEN st.tafPoints/200 ELSE 0 END) as femaleFriendReferrals
FROM st) AS subquery