Force 2 decimal place format in MySQL table - mysql

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

Related

how to convert table columns into a table in mysql?

I know it's a bad title, but I don't know how to describe my question in a line.
I want to store following information in my database.
+----+----------+-----------+-----------+
| id | name | cluster_1 | cluster_2 |
+----+----------+-----------+-----------+
| 1 | content_1| true| false |
| 2 | content_2| false| true |
| 3 | content_3| true| true |
+----+----------+-----------+-----------+
cluster_1=true means that the content exists on the cluster_1.
As some clusters may added or deleted, I want to store my cluster information in a new table "clusters", and indicate the relation between contents and clusters with a "content_cluster" table.
table contents
+----+----------+
| id | name |
+----+----------+
| 1 | content_1|
| 2 | content_2|
| 3 | content_3|
+----+----------+
table clusters
+----+----------+
| id | name |
+----+----------+
| 1 | cluster_1|
| 2 | cluster_2|
+----+----------+
table content_cluster
+----------+----------+
|content_id|cluster_id|
+----------+----------+
| 1 | 1 |
| 2 | 2 |
| 3 | 1 |
| 3 | 2 |
+----------+----------+
But, writing in this way, I don't know how to get a content which is on cluster_1 but isn't on cluster_2, or vice versa. I have to do this query frequently. So what is the efficient way to do this?
how to get a content which is on cluster_1 but isn't on cluster_2
in general
SELECT contents.name
FROM contents
JOIN content_cluster ON contents.id = content_cluster.content_id
LEFT JOIN clusters ON clusters.id = content_cluster.cluster_id
GROUP BY contents.name
HAVING SUM(clusters.name = 'cluster_1') -- not zero, may add ">0"
AND !SUM(clusters.name = 'cluster_2') -- zero, may replace NOT ("!") with "=0"
The following should work:
-- For cluster 1
INSERT INTO new_table (content_id, cluster_id)
SELECT old_table.content_id, 1
FROM old_table
WHERE old_table.cluster_1 = TRUE;
-- For cluster 2
INSERT INTO new_table (content_id, cluster_id)
SELECT old_table.content_id, 2
FROM old_table
WHERE old_table.cluster_2 = TRUE;

When inserting new record in existing table tt goes up instead of down

I have already created table I want to add extra row when adding extra row the created extra row goes up. I want that row at the bottom.
MariaDB [armydetails]> insert into armydetails values('r05','Shishir','Bhujel','Jhapa','9845678954','male','1978-6-7','1994-1-3','ran5','Na11088905433');
Query OK, 1 row affected (0.17 sec)
MariaDB [armydetails]> select * from armydetails;
+-------+---------+---------+-----------+------------+--------+------------+------------+--------+----------------+
| regNo | fName | lName | address | number | gender | DOB | DOJ | rankID | accountNo |
+-------+---------+---------+-----------+------------+--------+------------+------------+--------+----------------+
| r05 | Shishir | Bhujel | Jhapa | 9845678954 | male | 1978-06-07 | 1994-01-03 | ran5 | Na11088905433 |
| ro1 | Milan | Katwal | Dharan | 9811095122 | Male | 1970-01-03 | 1990-01-01 | ran1 | Na11984567823 |
| ro2 | Hari | Yadav | Kathmandu | 9810756436 | male | 1980-06-07 | 2000-05-06 | ran2 | Na119876678543 |
| ro3 | Khrisna | Neupane | Itahari | 9864578934 | male | 1980-02-02 | 2001-01-07 | ran3 | Na11954437890 |
| ro4 | Lalit | Rai | Damak | 9842376547 | male | 1989-05-09 | 2005-01-02 | ran4 | Na11064553221 |
+-------+---------+---------+-----------+------------+--------+------------+------------+--------+----------------+
5 rows in set (0.00 sec)
MariaDB [armydetails]>
The SQL 2011 publication from ISO/IEC 9075 says:
In general, rows in a table are unordered; however, rows in a table are ordered if the table is the result of a that immediately contains an « order by clause ».
In a SQL database, there is no underlying, default ordering for records. A relational database basically stores a table as a bunch of unordered records.
When records are SELECTed without an ORDER BY clause, they come out in an undefined order, that in no way is guaranteed to be consistent over subsequent queries (including the very same query being executed several times). This is true for MySQL and for other RDBMS.
The only way to properly order records is to use an ORDER BY clause, like:
select * from armydetails order by regNo
Suggested lecture: Tom Kyte Blog : Order in the Court!.
You can simply add an ORDER BY clause to your statment as follows:
SELECT * FROM armydetails ORDER BY regNO DESC;

INNER JOIN same value, but the difference is the other table are having extra word in front of the value

As I said in the title, or maybe my question is a little bit confusing. Here it is....
So, I want to combine 2 tables using INNER JOIN (ofcourse) with some difference.
This is my tables
Table 1, PK = steam_id
SELECT * FROM nmrihstats ORDER BY points DESC LIMIT 4;
+---------------------+----------------+--------+-------+--------+
| steam_id | name | points | kills | deaths |
+---------------------+----------------+--------+-------+--------+
| STEAM_0:1:88467338 | Alan14 | 50974 | 5438 | 12 |
| STEAM_0:0:95189481 | ? BlacKEaTeR ? | 35085 | 24047 | 316 |
| STEAM_0:1:79891668 | Lowell | 34410 | 44076 | 993 |
| STEAM_0:1:170948255 | Rain | 29780 | 30167 | 278 |
+---------------------+----------------+--------+-------+--------+
4 rows in set (0.01 sec)
Table 2, PK = authid
SELECT * FROM store_players ORDER BY credits DESC LIMIT 4;
+-----+-------------+---------------+---------+--------------+-------------------+
| id | authid | name | credits | date_of_join | date_of_last_join |
+-----+-------------+---------------+---------+--------------+-------------------+
| 309 | 1:88467338 | Alan14 | 15543 | 1475580801 | 1482260232 |
| 368 | 1:79891668 | Lowell | 10855 | 1475603908 | 1482253619 |
| 256 | 1:128211488 | Fuck[U]seLF | 10422 | 1475570061 | 1482316480 |
| 428 | 1:74910707 | Mightybastard | 7137 | 1475672897 | 1482209608 |
+-----+-------------+---------------+---------+--------------+-------------------+
4 rows in set (0.00 sec)
Now, how can I use INNER JOIN without doing like removing "STEAM_0:" or adding it. Also with explanation, please
You can join witn like operator, e.g.:
SELECT n.*, sp.*
FROM nmrihstats n JOIN store_players sp ON n.steam_id LIKE CONCAT('%', sp.authid);
Here's the SQL Fiddle.
Another approach would be to use String functions of MySQL to extract out relevant part from steam_id but I believe that's not what you want:
SELECT SUBSTR(steam_id, LOCATE('STEAM_0:', steam_id) + CHAR_LENGTH('STEAM_0:'))
FROM nmrihstats;
it is not possible, you need to remove "STEAM_0:", matching with WHERE, using substring for remove STEAM_0: from column equals to column in other table, or a new field into the T1 without "STEAM_0:", that 2 columns match for INNER JOIN

Approximate selection between decimal values in perl-DBI

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 |
+------+-------+----------+

Replacing the last characters of a string value with the id of the table

I have got the columns [id, account_id] in my table. And the values are
+------+----------------+
| id | account_id |
+------+----------------+
| 1 | 01-01-02-0007 |
| 2 | 04-05-06-0001 |
| 3 | 03-07-09-0001 |
| 4 | 03-04-04-0001 |
| 5 | 03-04-08-0101 |
| ... |
| 201 | 03-04-08-0111 |
+------+----------------+
What I want is replace the last part of the each of account_id after - i.e. 0007, 0001 and 0001 etc in this case with respective id (but still padded with the 0s to the left to make it 4 characters). To be more specific, below is what I want to achieve:
+------+----------------+
| id | account_id |
+------+----------------+
| 1 | 01-01-02-0001 |
| 2 | 04-05-06-0002 |
| 3 | 03-07-09-0003 |
| 4 | 03-04-04-0004 |
| 5 | 03-04-08-0005 |
| .... |
| 201 | 03-04-08-0201 |
+------+----------------+
I thought to use REPLACE but unfortunately, that can't be applied to my case, since it is not just the part ( that remains same for each value) that I want to change. I have been searching, but I am unable to achieve this. I think, I would have to use some regular expression and LPAD in some way to achieve this, but not sure how.
Can anyone please show me some light?
For the very simple case with fixed account number lengths you're showing, this will do;
UPDATE accounts
SET account_id=CONCAT(LEFT(account_id,9), LPAD(id, 4, '0'))
An SQLfiddle to test with.
If account_id format would not be changing, you can use
substring_index, lpad, and concat to apply changes as you wanted.
update my_table
set account_id =
concat( substring_index( account_id, '-', 3 ), '-', lpad( id, 4, '0' ) )