search the column with decimal value for '.' - sql

I have a table with a1 and a2 float columns,
The values in a2 are calculated from a1, as a2 = 3*a1
The condition is:
If the value in a1 is 9.5, I need to get the ceiling value in a2
i.e., if the numeric value after the decimal point is greater than or equal to 5 I need to get ceiling value, else I need to get the floor value.
I have written below query
SET a2 =(case when substring(cast((a1 * 3) as varchar(6)),CHARINDEX('.',(a1*3)),1) >=5 then CEILING(a1 * 3) else FLOOR(a1 * 3) end) from table
but it obviously returns the below error:
Conversion failed when converting the varchar value '.' to data type int.
Since it, can't take varchar into ceiling or floor.
Is there any way by which I can achieve this?
Your help will be greatly appreciated.
The value of a2 keeps changing based on a1, if a1 is 4.5 a2 should ceiling of that, if a1 is 4.9 a2 should be again ceiling value but if a1 is anything below 4.5 as 4.3,4.2,4.1 then it should be a floor value
Any other approach for this would also do except ceiling and floor.

How about using round()? It implements this logic directly in the database:
set a2 = round(a1, 0);
An alternative method is to subtract 0.5:
set a2 = floor(a1 + 0.5)
If you want a2 as a string value (you say you want a float but the code returns a string), then use str():
set a2 = str(a1)
str() rounds by default.

That because you trying to compare varchar >=5, cast it to INT:
SET a2 =(case when cast(substring(cast((a1 * 3) as varchar(6)),CHARINDEX('.',(cast((a1 * 3) as varchar(6))),1) as INT) >=5 then CEILING(a1 * 3) else FLOOR(a1 * 3) end) from table

Related

Convert string into very large integer in Hive

I have numeric values stored in a string column named "hst" in a hive table with 1636626 rows, but to perform arithmetic operations(comparison, difference), I need to convert the hst column into very large integers to preserve all the digits. here's a sample of my data:
id hst
A1 155836976724851034470045871285935636480
A2 55836976724791053359504802768816491263
B1 55836977111335639658316742086388875264
A3 55836977111354662261430576153184174079
C2 55836926053814078414548020414090575872
C4 55836926053833373226361854480885874687
B2 55836926013959368986746057541906857984
B4 55836926013959368635392801615616409599
C3 55836976724870256360155492454040600576
I tried decimal type:
SELECT cast('55836976724791053359504802768816491263' as DECIMAL(38, 0))
but as the max length of the field is 39 digits and decimal type allows 38 at most it doesn't work for the first value of the sample 155836976724851034470045871285935636480
Does anyone have an idea how to achieve that ?

How to put an upper bound over the sum of each row in a table in GAMS?

I have a table called "latencies" and it encompasses 2 sets, a and b, and a variable y to iterate over this table. As well, I have some parameters for a that must be satisfied:
table latencies(a, b)
b1 b2 b3
a1 1 2 3
a2 4 5 6
a3 7 9 8;
parameter pam1(a) /"a1" 12, "a2" 13, "a3" 14/;
positive variable y(a,b);
I am trying to make the sum of each row from the latencies table at most each respective element in the parameter pam1.
equations maxime(a), ...;
maxime(a)..
sum(a, y(a,b)) =l= pam1(a);
So the sum of the first row in latencies should be less than or equal to 12, the sum of the 2nd row should be less than or equal to 13, etc. However, I am getting these errors: "Set is under control already" and "Uncontrolled set entered as constant" on the same equation above. How do I do this?
Here is the corrected solution (which works):
equations maxime(a), ...;
maxime(a)..
sum(b, y(a,b)) =l= pam1(a);
I was incorrectly setting the row index (a) as my controlling index before. I needed to set that index as b, the column index. That is how you would iterate over the sum of each row and put an upper bound on it.

How to do typecasting without loosing a comma?

Task: I have data col(30) TYPE c VALUE '-1111,45'. and I need to check if this value is negative, if negative - do typecasting. But on the output I get 5 though I have to get 1111,45 without a minus and again do typecasting to the previous type (с).
REPORT Z_CAST.
data col(30) TYPE c VALUE '-1111,45'.
data numc type n.
numc = col.
if numc < 0.
numc = -1 * numc.
endif.
col = numc.
WRITE col. "Output: 5
REPORT Z_CAST.
data col(30) TYPE c VALUE '-1111,45'.
if col+0(1) EQ '-'.
WRITE col+1. "1111,45
endif.
This is the minimum character processing way to do this:
col = replace( val = col
sub = '-'
with = ' ' ).
You don't have to find the - first to replace it.
And this is the clean numeric way that ABAPers will usually choose:
DATA n TYPE p LENGTH 12 DECIMALS 2.
n = col.
n = abs( n ).
Note that this does not work with your example '-1111,45' though: ABAP expects a point . as decimal separator, but your number uses a localized format with comma ,, so you would have to normalize the number first.

Postgresql performing partitioning to find time difference

I am trying to fill column D and column E.
Column A: varchar(64) - unique for each trip
Column B: smallint
Column C: timestamp without time zone (excel messed it up in the
image below but you can assume this as timestamp column)
Column D: numeric - need to find out time from origin in minutes
column E: numeric - time to destination in minutes.
Each trip has got different intermediate stations and I am trying to figure out the time it has been since origin and time to destination
Cell D2 = C2 - C2 = 0
cell D3 = C3 - C2
Cell D4 = C4 - C2
Cell E2 = E6 - E2
Cell E3 = E6 - E3
Cell E6 = E6 - E6 = 0
The main issue is that each trip contains differnt number of stations for each trip_id. I can think about using partition by column but cant figure out how to implement it.
Another sub question: I am dealing with very large table (100 million rows). What is the best way Postgresql experts implement data modification. Do you create like a sample table from the original data and implement everything on the sample before implementing the modifications on the original table or do you use something like "Begin trasaction" on the original data so that you can rollback in case of any error.
PS: Help with question title appreciated.
you don't need to know the number of stops
with a as (select *,extract(minutes from c - min(c) over (partition by a)) dd,extract(minutes from max(c) over (partition by a) - c) ee from td)
update td set d=dd, e=ee
from a
where a.a = td.a and a.b=td.b
;
http://sqlfiddle.com/#!17/c9112/1

SQL - test if numeric field is holding an integer

I have numbers (from my select)
col1 col2
1. 3.6 and 3
2. 3.6 and 5
I want this
if(col1/col2 = integer)
update column
else(col1/col2 = decimal number)
update column
Any idea how to get is number integer or decimal?
You could use modulo 1 (% 1), and if the remainder is zero then you have your 'integer'. For example, with SQL Server:
if (col1 / col2 ) % 1 = 0
-- integer
else
-- decimal