Approximate selection between decimal values in perl-DBI - mysql

I was developed database table by using this query
create table test(
id varchar(10),
alpha varchar(1000),
marks decimal(10,4)
);
In the marks should use decimal datatypes.
marks column
1100.2523
1100.2722
733.8375
1192.257
587.6248
392.0859
I should use to select query
select * from test where marks="1100.2625";
and
select * from test where marks="392.0252";
The output is Empty set (0.00 sec)
Expected Output is
1100.2523 1100.2722 and 392.0859 this rows.
If possible to select between decimal range.?

This is usually not possible using the query and for that you need to define a benchmark for the approximation.
Now if you have a bench mark set for the approximation and lets say its something as
If the marks and compared value is same rounding to first decimal point then its a match.
If the after rounding to first decimal point both marks and input and taking the difference the value is 1 or -1 then its a match.
Using the above benchmark it could done.
Consider the following table
mysql> select * from test ;
+------+-------+-----------+
| id | alpha | marks |
+------+-------+-----------+
| 1 | aa | 1100.2523 |
| 2 | bb | 1100.2722 |
| 3 | cc | 392.0859 |
+------+-------+-----------+
mysql> select * from test where round(marks,1) = round(1100.2625,1);
+------+-------+-----------+
| id | alpha | marks |
+------+-------+-----------+
| 1 | aa | 1100.2523 |
| 2 | bb | 1100.2722 |
+------+-------+-----------+
mysql> select * from test
where round(marks,1) = round(392.0252,1)
or round(marks,1) - round(392.0252,1) = 0.1
or round(marks,1) - round(392.0252,1) = -0.1;
+------+-------+----------+
| id | alpha | marks |
+------+-------+----------+
| 3 | cc | 392.0859 |
+------+-------+----------+

Related

MySQL: Add Default Value to Joined Table when Row not Found

System info:
$ uname -srvm
Linux 5.15.0-56-generic #62-Ubuntu SMP Tue Nov 22 19:54:14 UTC 2022 x86_64
$ mysql --version
mysql Ver 8.0.31-0ubuntu0.22.04.1 for Linux on x86_64 ((Ubuntu))
I am very inexperienced with MySQL & have been looking for an answer to this for about half a week. I am working with two tables named character_stats & halloffame that I want to join in a query. They look like this:
mysql> SELECT name, level FROM character_stats;
+-----------+-------+
| name | level |
+-----------+-------+
| foo | 0 |
| bar | 0 |
| baz | 3 |
| tester | 4 |
| testertoo | 2 |
+-----------+-------+
mysql> SELECT * from halloffame;
+----+-----------+----------+--------+
| id | charname | fametype | points |
+----+-----------+----------+--------+
| 1 | bar | T | 0 |
| 2 | foo | T | 0 |
| 3 | baz | T | 0 |
| 4 | tester | T | 0 |
| 5 | testertoo | T | 0 |
| 6 | tester | D | 40 |
| 7 | tester | M | 92 |
| 8 | bar | M | 63 |
+----+-----------+----------+--------+
In my query, I want to display all the rows from character_stats & I want to join the points column from halloffame for fametype='M'. If there is no row for fametype='M', I want to set points to 0 for that character name, instead of omitting the entire row as is done in the following:
mysql> SELECT name, level, points FROM character_stats JOIN
-> (SELECT charname, points FROM halloffame WHERE fametype='M')
-> AS hof ON (hof.charname=name);
+--------+-------+--------+
| name | level | points |
+--------+-------+--------+
| tester | 4 | 92 |
| bar | 0 | 63 |
+--------+-------+--------+
So I want it to output this:
+-----------+-------+--------+
| name | level | points |
+-----------+-------+--------+
| foo | 0 | 0 |
| bar | 0 | 63 |
| baz | 3 | 0 |
| tester | 4 | 92 |
| testertoo | 2 | 0 |
+-----------+-------+--------+
I have tried to learn how to use IFNULL, IF-THEN-ELSE, CASE, COALESCE, & COUNT statements from what I have found in documentation & answers on stackoverflow.com. But as I said, I am very inexperienced & don't know how to implement them.
The following works on its own:
SELECT IFNULL((SELECT points FROM halloffame WHERE fametype='M'
AND charname='foo' LIMIT 1), 0) as points;
But I don't know how to join it to the character_stats table. The following would work if I knew how to get the value of character_stats.name before COALESCE is called:
SELECT name, level, 'M' AS fametype, points FROM character_stats
JOIN (SELECT COALESCE((SELECT points FROM halloffame WHERE
fametype='M' AND charname=name LIMIT 1), 0) AS points) AS hof;
According to Adding Default Values on Joining Tables I should be able to use CROSS JOIN, but I am doing something wrong as it still results in Unknown column 'cc.name' in 'where clause':
SELECT name, level, points FROM character_stats
CROSS JOIN (SELECT DISTINCT name FROM character_stats) AS cc
JOIN (SELECT COALESCE((SELECT points FROM halloffame WHERE
fametype='M' AND charname=cc.name LIMIT 1), 0) AS points) AS hof;
Some references I have looked at:
Returning a value even if no result
Usage of MySQL's "IF EXISTS"
Return Default value if no row found
MySQL.. Return '1' if a COUNT returns anything greater than 0
How do write IF ELSE statement in a MySQL query
Simple check for SELECT query empty result
Is there a function equivalent to the Oracle's NVL in MySQL?
MySQL: COALESCE within JOIN
Unknown Column In Where Clause With Join
Adding Default Values on Joining Tables
https://www.tutorialspoint.com/returning-a-value-even-if-there-is-no-result-in-a-mysql-query
I found that I can do the following:
SELECT name, level, COALESCE((SELECT points FROM
halloffame WHERE fametype='M' AND charname=name
LIMIT 1), 0) AS points FROM character_stats;
Though I would still like to know how to do it within a JOIN statement.

Force 2 decimal place format in MySQL table

mysql> select * from MyTable;
+----+--------+
| id | Va |
+----+--------+
| 1 | 77.218 |
| 2 | 34.43 |
| 3 | 909 |
+----+--------+
How do I update column Va to force both a permanent (1) round and (2) format to 2 d.p
Va is datatype FLOAT
This isn’t working:
UPDATE MyTable SET Va=FORMAT(ROUND(Va,2),2);
i.e. to: select *:
+--------------+
| 77.22 |
| 34.43 |
| 909.00 |
+--------------+
It is just leaving 909 at the bottom and not 909.00
Thanks for any help
Full Detail
mycursor = mydb.cursor()
def exe(_input):
mycursor.execute(_input)
exe("USE olbliss$CCE")
exe("DROP TABLE IF EXISTS MyTable")
exe('''CREATE TABLE MyTable
(id INT(6) AUTO_INCREMENT PRIMARY KEY,
Va FLOAT(30) NOT NULL)''')
exe("INSERT INTO MyTable (Va) VALUES ('77.218');")
exe("INSERT INTO MyTable (Va) VALUES ('34.43');")
exe("INSERT INTO MyTable (Va) VALUES ('909');")
exe("UPDATE MyTable SET Va=FORMAT(ROUND(Va,2),2);")
mysql> select * from MyTable;
+----+-------+
| id | Va |
+----+-------+
| 1 | 77.22 |
| 2 | 34.43 |
| 3 | 909 |
+----+-------+
If you want a fixed number of digits of scale, use DECIMAL(5,2) instead of FLOAT.
You can have greater precision, for example DECIMAL(9,2). I chose (5,2) in the example above because it was sufficient for the values you showed in your question.
Read more about it here: https://dev.mysql.com/doc/refman/8.0/en/fixed-point-types.html

SQL - Select column with certain value in it and other random values

Let me say i have a table called test with the following data
+---------+-----------------+
| id | t_number |
+---------+-----------------+
| 1 | 864291100247345 |
| 2 | 355488020906457 |
| 3 | 864296100098739 |
| 4 | 864296100098325 |
| 5 | 864296100119956 |
What i want to do is to be able to write a select statement that returns a 3 rows with two random values and one mandatory value from the t_number column
for example if the mandatory value is 864291100247345 the output should something like below
+---------+-----------------+
| id | t_number |
+---------+-----------------+
| 1 | 864291100247345 |
| 2 | 355488020906457 |
| 4 | 864296100098325 |
OR
+---------+-----------------+
| id | t_number |
+---------+-----------------+
| 1 | 864291100247345 |
| 3 | 864296100098739 |
| 4 | 864296100098325 |
I have tried the below query but it's not yielding the output i expect, in a sense that it does return a result but without the mandatory value
SELECT * FROM test WHERE t_number = 864291100247345 OR id LIMIT 3;
What is the best way to go about this?
Thank you.
You can use order by:
SELECT t.*
FROM test
ORDER BY (t_number = 864291100247345) DESC,
rand()
LIMIT 3;
This returns the mandatory number first and then random numbers after that.
MySQL treats boolean values (the result of the = expression) as numbers in a numeric context, with "1" for true and "0" for false. So the first expression in the order by sorts the result set with the "true" conditions first, followed by the others.

MySQL - add text prefix before column name in SELECT statement

Here is my table:
| ID | NUMBER |
| 1 | 523 |
| 2 | 293 |
| 3 | 948 |
And now, I want to get all NUMBER values but I want to add in result two numbers - 48 - (without upadting existing results). So finally I want print these results:
| NUMBER |
| 48523 |
| 48293 |
| 48948 |
So I need a query, something like this:
SELECT '48' + `number` FROM `table`
but this query doesn't work fine (this query only update column name from NUMBER to 48 + NUMBER).
Any ideas?
Thanks.
You need CONCAT
SELECT CONCAT('48' , `number`) AS number FROM table
Demo

MYSQL - Count items separated by comma or not

I have a tinytext field which can contain 3 differents value formatted as followed:
NULL
"X" or "Y" (where X and Y can be any number)
"A,B,C,D" (where A, B, C and D can be any number)
I want to query the table and count the number of items separated or not with a comma.
For example with these lines:
42
NULL
42,56,99
24,10090
Then the expected count would be 6.
I can't find the correct query.
Okay here's the test data:
mysql> create table t (f tinytext);
mysql> insert into t values ('42'), (null), ('42,56,99'), ('24,10090');
mysql> select * from t;
+----------+
| f |
+----------+
| 42 |
| NULL |
| 42,56,99 |
| 24,10090 |
+----------+
You can calculate how many numbers in the string as the difference in the length of the string and the string with commas removed (add 1 for the first number in the list).
mysql> select f, length(f), length(replace(f,',','')), 1+ length(f)-length(replace(f,',','')) from t;
+----------+-----------+---------------------------+----------------------------------------+
| f | length(f) | length(replace(f,',','')) | 1+ length(f)-length(replace(f,',','')) |
+----------+-----------+---------------------------+----------------------------------------+
| 42 | 2 | 2 | 1 |
| NULL | NULL | NULL | NULL |
| 42,56,99 | 8 | 6 | 3 |
| 24,10090 | 8 | 7 | 2 |
+----------+-----------+---------------------------+----------------------------------------+
So then use SUM() to get the total. SUM() ignores NULLs.
mysql> select sum(1+length(f)-length(replace(f,',',''))) from t;
+--------------------------------------------+
| sum(1+length(f)-length(replace(f,',',''))) |
+--------------------------------------------+
| 6 |
+--------------------------------------------+
This would be easier if you don't store comma-separated lists in a string.