Show zeroes if right two digits are zero - sql

I am having trouble solving this one. If i have the following values stored in U_pmHours
3.00
4.25
5.50
The following code correctly gives me the two digits after the decimal place
RIGHT(FORMAT(CONVERT(DECIMAL(4,2),T2.U_pmHours)/2,'N2'),2) AS 'TEST 2'
So the new values will be
00
25
50
The problem i am having is converting these values to minutes using * 60 /100, it works as it should on everything that isnt 00, instead of still showing 00 it shows as blank.
What can i do to make it either not do the calculation if the digits after the decimal are 00 (3.00) or to still show 00 in this case.

This has been solved. My problem was that I was trying to use two different field types in the same column. On one end i was performing a calculation for one instance and then providing a string for the other.
I resolved this by simply converting the calculated part of the code to also be a varchar type.
CASE WHEN
SUBSTRING(CONVERT(VARCHAR,CAST(T2.U_pmHours AS DECIMAL(4,2)) / 2),3,2) = '00'
THEN '00'
ELSE
CAST(SUBSTRING(CONVERT(VARCHAR,CAST(T2.U_pmHours AS DECIMAL(4,2)) / 2),3,2) * 60 / 100 AS VARCHAR)

Related

Going more than 24hrs and adding days

I have an expression in a table that is calculating the total of the column that has different times in it. But after the total goes over 24 hours it resets. I want to add to have days also in it if it goes more than 24hrs. I have so far added days in the format but this means that even with 0 days it gives 01 days since it is using the days section of the date. This is wrong and I either want to take one away from this ot have some sort of a counter to count the days. This is the expression if have so far:
=format(DateAdd("s", SUM(Fields!TotalDowntime.Value), "00:00:00"), "dd 'days' HH 'hrs' mm 'mins' ss 'secs'")
I have tried to format and using dateadd function to see if this can be done in a different way
The following isn't a full answer, but I'm hoping it will help you towards one. I think I've understood from your question that the field which records your TotalDowntime figure records this value in seconds.
SELECT
TotalDowntime/(24*60*60) as [days],
TotalDowntime/(60*60) % 24 as [hours],
TotalDowntime/(60) % 60 as [minutes],
TotalDowntime % 60 as [seconds]
FROM
MyTable
You'll see that all the parts simply cut off any decimals that result from the division. The % is SQL Servers "Mod" function that returns the remainder on division.
You should be able to put code similar to the above "server side" and concatenate these columns in reportbuilder (or server side if you wish).

Want to format a second to dd:hh:mm:ss to remove the zero values for readability in Excel 2016

I have the solution to convert seconds to a correct value of xx Days yy Hours zz Minutes aa Seconds and I want to know a way to have the output drop the values and labels if the value is 00.
Have been looking through several sites and found all the great ways to manipulate the seconds to change the format but I suspect I will need a function to get the desired output.
Here is my code to convert seconds to correct format:
=TEXT(G2/(24*60*60),"dd \D\a\y\s hh \H\o\u\r\s mm \M\i\n\u\t\e\s ss \S\e\c\o\n\d\s")
60 (as my source seconds) comes across in the output as 00 Days 00 Hours 01 Minutes 00 Seconds. I want it to say 01 Minutes with the other values removed. 12600 (as my source seconds) comes across in the output as 00 Days 03 Hours 30 Minutes 00 Seconds. I want it to say 03 Hours 30 Minutes with the other values removed.
You'll have to use =Concatenate(If(......)) to achieve this.
Just for the demonstration, I added 4 more columns, each for day, hour, minute and second and then concatenated them into one.
My data is at cell C2. And formulae are below :
Cell H2 : =TEXT(C$2/(24*60*60),"dd")
Cell I2 : =TEXT(C$2/(24*60*60),"hh")
Cell J2 : =TEXT(C$2/(24*60*60),"mm")
Cell K2 : =TEXT(C$2/(24*60*60),"ss")
The above four will just extract the actual number of day/hour/minute/second. And the following four will add suffix to it based on whether the value is zero or non-zero.
Cell L2 : =CONCATENATE(IF(H2<>"00",CONCATENATE(H2," days"),""))
Cell M2 : =CONCATENATE(IF(I2<>"00",CONCATENATE(I2," hours"),""))
...
...
Finally, just concatenate L2 through O2 to achieve desired result.
=CONCATENATE(L2," ", M2," ",N2," ",O2)
You might want to download the demo implementation from here.

Ingres multiplication gives wrong result

I have an Ingres table with following columns
from_date ingresdate
to_date ingresdate
model_amt money
The dates can reflect a period of any number of days, and the model_amt is always a weekly figure. I need to work out the the total model_amt for the period
To do this I need to know how many days are covered by the period, and then divide model_amt by 7, and multiply it by the number of days
however, I am getting incorrect results using the code below
select model_amt, date_part('day',b.to_date - b.from_date),
model_amt / 7 * int4( (date_part('day',b.to_date - b.from_date)) )
from table
For example, where model_amt = 88.82 and the period is for 2 weeks, I get the following output
+-------------------------------------------------------+
¦model_amt ¦col2 ¦col3 ¦
+--------------------+-------------+--------------------¦
¦ #88.82¦ 14¦ #177.66¦
+-------------------------------------------------------+
But 88.82 / 7 * 14 = 177.64, not 177.66?
Any ideas what is going on? The same issue happens regardless of whether I include the int4 function around the date_part.
* Update 15:28 *
The solution was to add a float8 function around the model_amt
float8(model_amt)/ 7 * interval('days', to_date - from_date)
Thanks for the responses.
In computers, floating point numbers are notoriously inaccurate. You can multiply do all kinds of basic mathematics calculations on floating point numbers and they'll be off by a few decimals.
Some information can be found here; but its very googleable :). http://effbot.org/pyfaq/why-are-floating-point-calculations-so-inaccurate.htm
Generally to avoid inaccuracies, you need to use a language specific feature (e.g. BigDecimal in Java) to "perfectly" store the decimals. Alternatively, you can represent decimals as separate integers (e.g. main number is one integer and the decimal is another integer) and combine them later.
So, I suspect this is just ingres showing the normal floating point inaccuracies and that there are known workarounds for it in that database.
Update
Here's a support article from Actian specifically about ingres floating point issues which seems useful: https://communities.actian.com/s/article/Floating-Point-Numbers-Causes-of-Imprecision.

NZSQL/Code - How to set NZSQL to NOT round to the nearest whole number

Everyone.
I am using some functions in NZSQL and am finding that NZSQL is rounding to the nearest whole number and was not sure if this is the design of the functions, or if the rounding could be disabled.
One of the functions that I am using is
TO_NUMBER(AGE(column_a),'000')
and it rounds to the nearest number, but I would like to have it leave it at a decimal number. Something like 12.42. Is this possible? Should I be using a different function? I have tried using '00.000) but it still rounds...
Thanks in advance!
The AGE function returns an interval which may not behave as you'd expect/hope when paired up with TO_NUMBER's format templates. The shape of the templates has a particular meaning that is different than what you might intuit.
For example, here I have a format template that corresponds to NUMERIC(20,6)
SYSTEM.ADMIN(ADMIN)=> select age('01/01/1960'::date) , to_number(age('01/01/1960'::date),'99999999999999999999.999999');
AGE | TO_NUMBER
-----------------------------------+---------------------
54 years 11 mons 15 days 23:17:21 | 541115231721.000000
(1 row)
Here you can see the interval expressed as digits in the result of the TO_NUMBER. The first two digits represent the 54 years, the next two represent the 11 months, and the last two before the decimal point represent the 21 seconds. Note that there is no value past the decimal point, and this is expected (well, by the design if not by us).
If we take one 9 off the template to the right or the left of the decimal point we get a malformed response. Notice that the 48 seconds is truncated to just a 4.
SYSTEM.ADMIN(ADMIN)=> select age('01/01/1960'::date) , to_number(age('01/01/1960'::date),'9999999999999999999.999999'), to_number(age('01/01/1960'::date),'99999999999999999999.99999');
AGE | TO_NUMBER | TO_NUMBER
-----------------------------------+--------------------+--------------------
54 years 11 mons 15 days 23:27:48 | 54111523274.000000 | 54111523274.000000
(1 row)
The point there was just to highlight that the format of the TO_NUMBER template does something other than what you likely expect/want.
What you probably want instead (if I get the right gist from your comment) is something like this, which uses DATE_PART as a loose substitute for DATEDIFF:
SYSTEM.ADMIN(ADMIN)=> select date_part('day',now() - '01/01/1960'::date) / 365.242;
?COLUMN?
------------
54.9580826
(1 row)

Sum function doesn't give sufficient decimal places with divide function

I have the following sql query that I am running:
select sum(cast(mkt_value as decimal(20,7)))/1204438043.37 from table1
and I get the following result which is correct but I need at least 10 decimal places not 6:
0.009347
If I run the following query:
select sum(mkt_value) from table1
I get 11258490.2400.
If I divide 11258490.24 by 1204438043.37 in excel I get 0.009347504674 which is the answer I'm looking for.
Please help me correct my SQL!!
Your cast is breaking this. It doesn't have enough space to give you more than six decimal places. What you're saying is literally "give me the result of this division with at most six decimal places", and then you're suprised the result only has six decimal places :)
The solution is either to omit the cast (if the data type is money, it's fine) or increase the scale of the decimal, eg. decimal(20, 11). The second parameter of the decimal type says the maximal amount of decimal places (-1) in the number. Also, consider only casting the result of the sum instead of all the items.
Note that most operations in MS SQL return a value of the same data type. So:
select 3 / 4; -- Returns 0
select cast(1000 as smallint) * cast(1000 as smallint);
-- Error - 1 000 000 is too big for smallint
The same thing happens in your sum and also in the division that happens right after it :)
You need to apply casting after calculating final value
select CAST (sum(mkt_value)/1204438043.37 as decimal(15,10)) from table1.
This means result would be having maximum 15 digits and mandatory 10 decimal places.
I would suggest the following query,Since your final decimal places are getting truncated.Hence a cast would be required to your final result set.
select
cast(cast (sum(mkt_value) as decimal(20,7))/cast (1204438043.37 as decimal(20,7)) as decimal(20,12)) from table1
Thank you..Let me know if this works