MySQL String to Time Trouble - mysql

I have my time data stored in a MySQL Row called "timestart" and I have three rows containing the values 9:00am, 10:00am, 1:00pm and I am trying to pull these out in a sorted order using the STR_TO_DATE function in my MySQL query. Here is the statement I am using:
SELECT * FROM db.test WHERE name='Name' and dateusing='2015-10-21' ORDER BY STR_TO_DATE('timeusingstart', '%h:%i%p');
It runs successfully but the rows get returned in the order of 10:00am, 9:00am, 1:00pm when I need them to be sorted in the time sequential order. I used the %h:%i%p based on the information I found at this documentation. Can anyone tell me what I'm doing wrong here? Thanks very much!

You're not running STR_TO_DATE() on the column, you're running it on a string. Try removing the quotes from around timeusingstart and it should work.
By the way, MySQL provides excellent documentation of all their functions!
mysql> create table test (test varchar(255));
Query OK, 0 rows affected (0.06 sec)
mysql> insert into test values('9:00am'), ('10:00am'), ('1:00pm');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from test order by str_to_date(test, '%h:%i%p');
+---------+
| test |
+---------+
| 9:00am |
| 10:00am |
| 1:00pm |
+---------+
3 rows in set (0.01 sec)

Your statement is nearly correct. You need to remove the quotes around first parameter for STR_TO_DATE, it is parsing a string you provided, not a value of the column - timeusingstart.
STR_TO_DATE(timeusingstart, '%h:%i%p');

Related

Nested Loop Calculation

Okay so maybe this is way deeper than I will ever need to go however I want to be able to analyze this nested loop so that I can understand it.
Given:
mysql> describe t1;
+-------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| dt | datetime | NO | MUL | NULL | |
+-------+----------+------+-----+---------+-------+
1 row in set (0.00 sec)
And:
mysql> insert t1 values(101),(102),(103),(104),(105),(106),(107),(#c:=now());
Query OK, 8 rows affected (0.03 sec)
Records: 8 Duplicates: 0 Warnings: 0
And:
mysql> insert t1 select #c:=#c+interval 1 second from t1,t1 b,t1 c,t1 d,t1 e,t1 f;
Query OK, 262144 rows affected (1.94 sec)
Records: 262144 Duplicates: 0 Warnings: 0
So far I have the understanding that (#ofrows)^(#oftables)=(# of rows Added)
My question is why this is the case. I cannot find out exactly how MySQL is handling the rows and other system variables in order to create the equation that I have provided here. My equation is clearly a simplified version of the resulting action performed by the server as using 2 rows of data and 6 tables similarly gives an output of 64.
Does anyone know exactly how this is manipulated? I have been working on this for 2 days and I cannot get my mind off of it...
Also why is it inserting more than 6... maybe 36? rows into the table in the first place?? it is only specifying one possible select-able row from the tables and that is the previously inserted now() and then adding 1 second to that row and resetting the #c based on the final change so shouldn't it by logic only insert a few rows?
I guess to put it simply I understand what is happening specifically in the select #c:=#c+interval 1 second portion of the statement, but after that I am not quite sure...
I guess to put it simply how does:
select #c:=#c+interval 1 second;
+--------------------------+
| #c:=#c+interval 1 second |
+--------------------------+
| 2014-07-20 18:17:50 |
+--------------------------+
1 row in set (0.00 sec)
turn into this:
...
Query OK, 262144 rows affected (1.94 sec)
Records: 262144 Duplicates: 0 Warnings: 0
The answer that was satisfactory for me on this issue was so simple I can't believe that I didn't realize it before now.
Today I needed to quickly fill a table with values so I decided to use another table that I had to do this. For example take table i which has the column i with values 1-50. I executed the following command to populate my table c column i.
insert into c select i.i from i,i b;
Based on my knowledge above I know that this would fill table c with exactly 2500 values. being that it executed the 50^2.
What I actually found that this was doing was examining each row from table i and multiplying it by the count of rows found in the first buffered instance i b and then inserting the resulting rows into the table. If you have more buffered instances it will get the results from one and then proceed to multiply those results further by the original 50 rows that would be found in the instance (for example i c).
I ended up with 50 rows of 1-50 within table c.
I didn't realize that this match based multiplication was being performed in this way before because I was using an incrementing operator and it would incrementally create new rows based on this multiplication, however it did not leave any indication that this is what it did due to the fact that it was not matching rows to duplicate rather it matched the number of rows to insert.

Mysql-If I insert multiple values in a column of a table simultaneously ,is it possible that the inserting orders of values get change?

I am doing these :
insert into table_name(maxdate) values
((select max(date1) from table1)), -- goes in row1
((select max(date2) from table2)), -- goes in row2
.
.
.
((select max(date500) from table500));--goes in row500
is it possible that while insertion , order of inserting might get change ?.Eg when i will do
select maxdate from table_name limit 500;
i will get these
date1 date2 . . date253 date191 ...date500
Short answer:
No, not possible.
If you want to double check :
mysql> create table letest (f1 varchar(50), f2 varchar(50));
Query OK, 0 rows affected (0.00 sec)
mysql> insert into letest (f1,f2) values
( (SELECT SLEEP(5)), 'first'),
( (SELECT SLEEP(1)), 'second');
Query OK, 2 rows affected, 1 warning (6.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from letest;
+------+--------+
| f1 | f2 |
+------+--------+
| 0 | first |
| 0 | second |
+------+--------+
2 rows in set (0.00 sec)
mysql>
SLEEP(5) is the first row to be inserted after 5 seconds,
SLEEP(1) is the second row to be inserted after 5+1 seconds
that is why query takes 6 seconds.
The warning that you see is
mysql> show warnings;
+-------+------+-------------------------------------------------------+
| Level | Code | Message |
+-------+------+-------------------------------------------------------+
| Note | 1592 | Statement may not be safe to log in statement format. |
+-------+------+-------------------------------------------------------+
1 row in set (0.00 sec)
This can affect you only if you are using a master-slave setup, because the replication binlog will not be safe. For more info on this http://dev.mysql.com/doc/refman/5.1/en/replication-rbr-safe-unsafe.html
Later edit: Please consider a comment if you find this answer not usefull.
Yes, very possible.
You should consider a database table unordered, and a SELECT statement without ORDER clause as well. Every DBMS can choose how to implement tables (often even depending on Storage Engine) and return the rows. Sure, many DBMS's happen to return your data in the order you inserted, but never rely on it.
The order of the retrieved data my depend on the execution plan, and may even be different when running the same query multiple times. Especially when only retrieving part of the data (TOP/LIMIT).
If you want to impose an order, add a field which orders your data. Yes, an autoincrement primary key will be enough in many cases. If you think you'll be wanting to change the order someday, add another field.

Storing 0.5 in MySQL

Using a decimal (I have tried variations of it) 0.5 is always converted to 5.
I can store 1.5, etc, no problem... Just curious on how I need to set up my data type to correctly store a '0.5' number.
Thanks
EDIT:
The current data type is Decimal (3,1). I have tried float as well.
I simply retreive the number through $_POST from a Form text box which is restricted to numbers only through Java. I never considered that maybe the browser is simply sending it as a 5, I don't know.
EDIT 2: I have confirmed through echo that the 0.5 is sent fine, it's once it gets into the database that it becomes 5
You know, I might get voted down for this, but I've always had success (as a sort of hack) in storing values like this as a VARCHAR and then using format() function in PHP when I need to make calculations. MySQL still seems to parse it well enough for SQL functions as well. Just my 2 cents :)
I used a decimal value in a database with various inputs:
I have tried to recreate you issue, but I get the following:
mysql> create table test(myDec decimal(2,2));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into test values(0.5);
Query OK, 1 row affected (0.01 sec)
mysql> insert into test values(.5);
Query OK, 1 row affected (0.00 sec)
mysql> select * from test;
+-------+
| myDec |
+-------+
| 0.50 |
| 0.50 |
+-------+
2 rows in set (0.00 sec)
Given your edit, I think that you might be getting values from international visitors, where the decimal point might be formatted using a comma instead of a dot?
mysql> insert into test values('0,5');
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select * from test;
+-------+
| myDec |
+-------+
| 0.50 |
| 0.50 |
| 0.00 |
+-------+
3 rows in set (0.00 sec)

MySQL always returning BIT values as blank

From my create table script, I've defined the hasMultipleColors field as a BIT:
hasMultipleColors BIT NOT NULL,
When running an INSERT, there are no warnings thrown for this or the other BIT fields, but selecting the rows shows that all BIT values are blank.
Manually trying to UPDATE these records from the command line gives odd effect - shows that the record was match and changed (if appropriate), but still always shows blank.
Server version: 5.5.24-0ubuntu0.12.04.1 (Ubuntu)
mysql> update pumps set hasMultipleColors = 1 where id = 1;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0
mysql> select hasMultipleColors from pumps where id = 1;
+-------------------+
| hasMultipleColors |
+-------------------+
| |
+-------------------+
1 row in set (0.00 sec)
mysql> update pumps set hasMultipleColors = b'0' where id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select hasMultipleColors from pumps where id = 1;
+-------------------+
| hasMultipleColors |
+-------------------+
| |
+-------------------+
1 row in set (0.00 sec)
Any thoughts?
You need to cast the bit field to an integer.
mysql> select hasMultipleColors+0 from pumps where id = 1;
This is because of a bug, see: http://bugs.mysql.com/bug.php?id=43670. The status says: Won't fix.
You can cast BIT field to unsigned.
SELECT CAST(hasMultipleColors AS UNSIGNED) AS hasMultipleColors
FROM pumps
WHERE id = 1
It will return 1 or 0 based on the value of hasMultipleColors.
You need to perform a conversion as bit 1 is not printable.
SELECT hasMultipleColors+0 from pumps where id = 1;
See more here:
http://dev.mysql.com/doc/refman/5.0/en/bit-field-literals.html
The actual reason for the effect you see, is that it's done right and as expected.
The bit field has bits and thus return bits, and trying to output a single bit as a character will show the character with the given bit-value – in this case a zero-width control character.
Some software may handle this automagically, but for command line MySQL you'll have to cast it as int in some way (e.g. by adding zero).
In languages like PHP the ordinal value of the character will give you the right value, using the ord() function (though to be really proper, it would have to be converted from decimal to binary string, to work for bit fields longer than one character).
EDIT:
Found a quite old source saying that it changed, so a MySQL upgrade might make everything work more as expected: http://gphemsley.wordpress.com/2010/02/08/php-mysql-and-the-bit-field-type/

MySql FLOAT datatype and problems with more then 7 digit scale

We are using MySql 5.0 on Ubuntu 9.04. The full version is: 5.0.75-0ubuntu10
I created a test database. and a test table in it. I see the following output from an insert statement:
mysql> CREATE TABLE test (floaty FLOAT(8,2)) engine=InnoDb;
Query OK, 0 rows affected (0.02 sec)
mysql> insert into test value(858147.11);
Query OK, 1 row affected (0.01 sec)
mysql> SELECT * FROM test;
+-----------+
| floaty |
+-----------+
| 858147.12 |
+-----------+
1 row in set (0.00 sec)
There seems to be a problem with the scale/precision set up in mySql...or did I miss anything?
UPDATE:
Found a boundary for one of the numbers we were inserting, here is the code:
mysql> CREATE TABLE test (floaty FLOAT(8,2)) engine=InnoDb;
Query OK, 0 rows affected (0.03 sec)
mysql> insert into test value(131071.01);
Query OK, 1 row affected (0.01 sec)
mysql> insert into test value(131072.01);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM test;
+-----------+
| floaty |
+-----------+
| 131071.01 |
| 131072.02 |
+-----------+
2 rows in set (0.00 sec)
mysql>
Face Palm!!!!
Floats are 32 bit numbers stored as mantissa and exponents. I am not 100% sure how MySql will split the storage but taking Java as an example they would use 24 bits for a signed mantissa and 8 bits for an exponent (scientific notation). This means that the maximum value a FLOAT can have is +8388608*10^127 and the minimum is -8388608*10^127. This means only 7 significant digits, and my FLOAT definition used 8.
We are going to switch all of these 8,2 to DOUBLE from FLOAT.
MySQL docs mention "MySQL performs rounding when storing values" and I suspect this is the issue here. I duplicated your issue but changed the storage type to be DOUBLE:
CREATE TABLE test (val, DOUBLE);
and the retrieved value matched the test value you provided.
My suggestion, for what it's worth, is use DOUBLE or maybe DECIMAL. I tried the same original test with:
CREATE TABLE test (val, DECIMAL(8,2));
and it retrieved the value I gave it: 858147.11.