Get floating point numbers from a list - mysql

I am working with a table having amount field of type DECIMAL(5,2). The values in the column are
id amount
1 9.00
2 1.83
3 7.01
4 8.00
5 99.85
I have to get the columns with only that have nonzero after decimal.
From the above list i should get
id amount
2 1.83
3 7.01
5 99.85
How should i write the query to get the result?
I am using MySql 5.6.

Just a guess:
SELECT *
from tblname
where amount=FLOOR(amount)

Related

what is the correct way to select the highest value from column not primary key

I have a table (report) consist of several records and one of them about int values (column) I am trying to get the highest number of the fall_value column the id only primary key, the table as following:
id (P)
fall_value
date
3
1.2
2021-01-29
4
1.5
2021-01-30
5
1.6
2021-01-30
6
1
2021-01-31
7
5
2021-01-31
8
1.5
2021-01-31
9
1.5
2021-01-31
10
14
2021-01-31
11
15
2021-01-31
expected result: 15
I have tried the following inquiry:
SELECT max(fall_value) from report;
I got an unexpected result: 5
and also I got a message saying:
Current selection does not contain a unique column. Grid edit, checkbox, Edit, Copy and Delete features are not available
It sounds like fall_value is a string, not a number, and the string "5" is indeed greater than the string "15".
Try converting to a number. A convenient way is to use implicit conversion:
SELECT max(fall_value + 0)
FROM report;

Exclude the combination of 2 columns only from my query

Sounds simple but I couldn't find the solution for it.
I have a table with 3 columns. Account, Amount, Date.
I want to get all entries except the ones of one specific account with negative amount. But I still want to get the entries of this account if amount value is positive.
So with this query I'm also not getting the entries from account1 with a positive amount.
select * from table where (account!='account1' AND amount<='0') AND date='2020-05-01'
You can do this using WHERE NOT in your statement.
Example schema:
Account Amount Date
=====================================
1 Ben 200 2020-10-10
2 Frank 200 2020-10-10
3 Ben -300 2020-10-12
4 Ben 10 2020-10-16
5 Mary 2000 2020-10-16
6 Frank -200 2020-10-18
7 Ben -10 2020-10-18
8 Ben 0 2020-10-20
Now if you build your query like this
SELECT * FROM t1 WHERE NOT (account='Ben' AND amount<0);
you should get what you want (all records except the 3rd and 7th).
Edit: if you really only want to exclude records with negative amounts, you need to do < rather than <= as you did in your example above. Depends on whether you want row 8 to be included in the result or not.

Aggregate values based on a date interval

I have a database containing monthly precipitation values at some measurements locations. The structure of my table is:
describe pp_lunare;
Field Type Null
ID int(11) NO
DATA_OBS date NO
PLUTON float NO
LEGHIN float NO
DUMBRAVA float NO
A sample of my data:
ID DATA_OBS PLUTON LEGHIN DUMBRAVA
1 1977-01-01 14.4 33.3 25.1
2 1977-02-01 18.7 12.9 13.2
3 1977-03-01 32.8 26.7 18.3
4 1977-04-01 109.6 123.8 140.6
5 1977-05-01 98.5 104.7 59.9
6 1977-06-01 192.9 172.8 66.6
7 1977-07-01 101.4 85.8 79.4
8 1977-08-01 116.4 103.3 105.7
9 1977-09-01 54.5 47.4 51.8
10 1977-10-01 23.6 15.6 11
11 1977-11-01 59.7 44.3 29.7
12 1977-12-01 28.7 13.1 10
In my case I need to get the sum of the precipitation for every column at every 3 months something like this:
ID DATA_OBS PLUTON LEGHIN DUMBRAVA
1 1977-03-01 65.9 72.9 56.6
2 1977-06-01 401 401.3 267.1
3 1977-09-01 272.3 236.5 247.9
and so on...
Thanks.
You can get the month from your date with month(data_obs) which returns a month from 1 to 12. Convert this to a value for the quarter by doing something like floor((month(data_obs) - 1)/3) as quarter to get quarters from 0 to 3.
For example, select data_obs, concat(year(data_obs), floor((month(data_obs) - 1)/3)) as quarter from pp_lunare; should show you both the original date and the derived quarter side by side.
Then group by this new value and sum the rest:
select concat(year(data_obs), floor((month(data_obs) - 1)/3)) as quarter, sum(pluton), sum(leghin), sum(dumbrava)
from pp_lunare
group by quarter
order by quarter;
If you want the exact date format you had in the question, you'll have to do a little bit of string manipulation (add 1 to the quarter above, multiply that by 3, pad with 0s, then tack on a "-01" for the date).
You can get the month data at first, and convert it into [quarter], which is from 0 to 2.
Then you can create three temporary tables given [quarter]=0,1,2,
and the easy and final part will be to add up the i_th row in these tables, the result will be just like below. And you can also have the data_obs data as well.
ID DATA_OBS PLUTON LEGHIN DUMBRAVA
1 1977-03-01 65.9 72.9 56.6
2 1977-06-01 401 401.3 267.1
3 1977-09-01 272.3 236.5 247.9

Mysql query contains

Table
id name(varhcar)
2 15
3 15,23
4 1315,424
5 1512,2323
6 23,15,345
7 253,234,15
I need to find out those values which contains 15 which mean i need 2,3,6,7 not 4,5.
Above is sample data, in real time it can be any number.
Can anyone please help me?
If your database is small, consider using find_in_set function:
select * from your_table
where find_in_set('15',name);
Consider change the model to master-detail table to increase the speed if you have a big table.
This is the kind of relational model you could adopt to make this an easy problem to solve:
TABLE: records
id
2
3
4
5
6
7
TABLE: values
record_id value
2 15
3 15
3 23
4 1315
4 424
5 1512
5 2323
6 23
6 15
6 345
7 253
7 234
7 15
Then you can query:
SELECT DISTINCT id FROM records
INNER JOIN values ON records.id = values.record_id AND values.value = 15
This is the only way you can take good advantage of MySQL's query optimizer.
Not that it's impossible to do what you're trying to do, but it kind of misses the point.
If you're already storing data in this format, you should write a one-time migration to transfer it to this "normalized" format in the programming language of your choice, using something like Java's split or PHP's explode.

MySQL: Matching inexact values using "ON"

I'm way out of my league here...
I have a mapping table (table1) to assign particular values (value) to a whole number (map_nu). My second table (table2), is a collection of averages (avg) for each user (user_id).
(I couldn't figure out how to properly make a markdown table, please feel free to edit!)
table1: table2:
(value)(Map_nu) (user_id)(avg)
---- -----
1 1 1 1.111
1.045 2 2 1.2
1.09 3 3 1.33333
1.135 4 4 1
1.18 5 5 1.389
1.225 6 6 1.42
1.27 7 7 1.07
1.315 8
1.36 9
1.405 10
The value Map_nu is a special number that each user gets assigned according to their average. I need to find a way to match the averages from table2 to the closest value in table1. I only need to match to the 2 digit past the decimal, so I've added the Truncated function
SELECT table2.user_id, map_nu
FROM `table1`
JOIN table2 ON TRUNCATE(table1.value,2)=TRUNCATE(table2.avg,2)
I still miss the values that don't match the averages exactly. Is there a way to pick the nearest truncated value or even to round to the second decimal? Rounding up/down wont matter as long as its applied to all values the same.
I am trying to have the following result (if rounded up):
(user_id)(Map_nu)
----
1 4
2 6
3 6
4 1
5 10
6 11
7 3
Thanks!
i think you might have to do this in 2 separate queries. there is no 'nearest' operator in sql, so you can either calculate it in your software, or you could use
select map_nu from table1 ORDER BY abs(value - $avg) LIMIT 1
inside a loop. however, that cannot be used as a join function as it requires the ORDER and LIMIT which are not valid as joins.
another way of looking at it is it seems that your map_nu and value are deterministic in relation to each other - value = 1 + ((map_nu - 1) * 0.045) - so maybe you could make use of that fact and calculate an integer based on that equation? assuming that relationship holds true for all values of map_nu.
This is an awkward database design. What is the data representing and what are you trying to solve? There might be a better way.
Maybe do something like...
SELECT a.user_id, b.map_nu, abs(a.avg - b.value)
FROM
table2 a
join table1 b
left join table1 c on abs(a.avg - b.value) > abs(a.avg - c.value)
where c.value is null
order by a.user_id
Doesn't actually produce the same output as the one you were expecting for (doesn't do any rounding). Though you should be able to tweak it from there. Above query will produce the output below (w/ data you've provided):
user_id map_nu abs(a.avg - b.value)
------- ------ --------------------
1 3 0.0209999999999999
2 5 0.02
3 8 0.01833
4 1 0
5 10 0.016
6 10 0.0149999999999999
7 3 0.02
Beware though if you're dealing with large tables. Evaluate the explain of the above query if it'll be practical to run it within MySQL or if better to be done outside it.
Note 2: Will produce duplicate rows if there are avg values that are equi-distant to value values within table1 (Ex. if value for map_nu's 11 and 12 are 2 and 3 and someone get's an avg of 2.5). Your question doesn't really specify what to do for that so you might want to take that into account.
Its taking a little extra work, but I figure the easiest way to get my results will be to map all values to the second decimal place in table1:
1 1
1.01 1
1.02 1
1.03 1
1.04 1
1.05 2
1.06 2
1.07 2
1.08 2
1.09 3
1.1 3
1.11 3
1.12 3
1.13 3
1.14 4
...
Thanks for the suggestions! Sorry I couldn't present the question more clear.