I want to delete rows from a table that has a column more than 7200 secs old.
The Query
mysql_query("delete from logged where DATE_ADD ( log, INTERVAL $this->loginDuration SECOND) < NOW()",$this->link);
where:
name of table = logged;
name of column = log;
$this->loginDuration = 7200;
The value of log in db: 2011-06-25 09:56:51.
Todays date and time [ Now() ] : 2011-07-05 11:39:02
The query is meant to delete the row with log value 2011-06-25 09:56:51 because it is older than 7200 seconds but it does not.
What am I not getting right?
You have a space between DATE_ADD and the parenthesis: ( log, ....
Use DATE_ADD( log, ...
From MySQL docs, Functions and Operators :
Note
By default, there must be no
whitespace between a function name and
the parenthesis following it. This
helps the MySQL parser distinguish
between function calls and references
to tables or columns that happen to
have the same name as a function.
However, spaces around function
arguments are permitted.
And:
You can tell the MySQL server to
accept spaces after function names by
starting it with the
--sql-mode=IGNORE_SPACE option. (See Section 5.1.6, “Server SQL Modes”.)
Individual client programs can request
this behavior by using the
CLIENT_IGNORE_SPACE option for
mysql_real_connect(). In either case,
all function names become reserved
words.
I wanted to show you what I did (could not post this as a comment)
+----------------------+
| temp.d(table.column) |
+----------------------+
| 2011-07-05 22:08:20 |
| 2011-07-05 22:08:20 |
| 2011-07-05 22:08:21 |
| 2011-07-05 22:08:21 |
| 2011-07-05 22:08:22 |
| 2011-07-05 22:08:22 |
| 2011-07-05 22:08:23 |
| 2011-07-05 22:08:23 |
| 2011-07-05 22:08:24 |
| 2011-07-05 22:08:24 |
+----------------------+
10 rows in set (0.00 sec)
mysql> delete from temp where DATE_ADD(d, INTERVAL 1 SECOND) < NOW();
Query OK, 10 rows affected (0.01 sec)
Related
Now my problem is to know a mysql query will fetch result which exceeds a certain row count (like 5000 rows). I know it can use select * ... limit 5001 to replace count() for performance optimization in terms of time effeciency, but it still return 5001 row of records which is totally useless in my scenario, becasue all I want is a sample 'yes/no' answer. Is there any better approach? big thanks ! ^_^
The accepted answer in the link provided by Devsi Odedra
is substantially correct but if you don't want a big result set select a column into a user defined variable and limit 1
for example
MariaDB [sandbox]> select * from dates limit 7;
+----+------------+
| id | dte |
+----+------------+
| 1 | 2018-01-02 |
| 2 | 2018-01-03 |
| 3 | 2018-01-04 |
| 4 | 2018-01-05 |
| 5 | 2018-01-06 |
| 6 | 2018-01-07 |
| 7 | 2018-01-08 |
+----+------------+
SELECT SQL_CALC_FOUND_ROWS ID INTO #ID FROM DATES WHERE ID < 5 LIMIT 1;
SELECT FOUND_ROWS();
+--------------+
| FOUND_ROWS() |
+--------------+
| 4 |
+--------------+
1 row in set (0.001 sec)
SELECT 1 FROM tbl
WHERE ... ORDER BY ...
LIMIT 5000, 1;
will give you either a row or no row -- This indicates whether there are more than 5000 row or not. Wrapping it in EXISTS( ... ) turns that into "true" or "false" -- essentially the same effort, but perhaps clearer syntax.
Caution: If the WHERE and ORDER BY are used but cannot handled by an INDEX, the query may still read the entire table before getting to the 5000 and 1.
When paginating, I recommend
LIMIT 11, 1
to fetch 10 rows, plus an indication that there are more rows.
The MySQL 5.7 docs seem to imply that a column with datatype DATETIME(3) will store and format a datetime value to precisely three milliseconds.
Link to docs
The relevant example from the docs:
mysql> CREATE TABLE fractest( c1 TIME(2), c2 DATETIME(2), c3 TIMESTAMP(2) );
mysql> INSERT INTO fractest VALUES
('17:51:04.777', '2018-09-08 17:51:04.777', '2018-09-08 17:51:04.777');
mysql> SELECT * FROM fractest;
+-------------+------------------------+------------------------+
| c1 | c2 | c3 |
+-------------+------------------------+------------------------+
| 17:51:04.78 | 2018-09-08 17:51:04.78 | 2018-09-08 17:51:04.78 |
+-------------+------------------------+------------------------+
In that example, c2 rounds to and displays exactly .78 seconds.
When I try to do the same thing with a DATETIME(3) column, MySQL correctly truncates to three fractional seconds places, but still formats to six places. So, the last three places are always zero, but it's formatting to show the microseconds place.
+----------------------------+
| timestamp |
+----------------------------+
| 2018-04-12 14:08:19.296000 |
| 2018-04-13 14:08:22.312000 |
| 2018-04-14 14:08:25.914000 |
+----------------------------+
How can I replicate the behavior from the MySQL docs? If the field is DATETIME(3), I'd like it to only display to the third fractional second place:
+-------------------------+
| timestamp |
+-------------------------+
| 2018-04-12 14:08:19.296 |
| 2018-04-13 14:08:22.312 |
| 2018-04-14 14:08:25.914 |
+-------------------------+
I'd also prefer to have it be the default behavior, rather than having to call a formatting function on timestamp on every select.
This was a side effect of using the mycli MySQL command line tool. It does not occur when using standard mysql.
I want to select a random record from a big table. After search, found two solutions finally;
a:
select id from `table` where id = (floor(1 + rand() * 2880000));
b:
select id from `table` where id >= (floor(1 + rand() * 2880000)) limit 1;
But first(a) solution is far slowly than Second(b), about 40 times slowly.
After execute many times, I find a more weird problem. First solution may return two record.
select id from `table` where id = (floor(1 + rand() * 2880000));
+---------+
| id |
+---------+
| 2484024 |
| 1425029 |
+---------+
2 rows in set (1.06 sec)
My question is:
Why is first solution slowly than second solution?
Why did first solution return two record?
My MySQL version:
mysql> show variables like "%version%";
+-------------------------+-------------------------+
| Variable_name | Value |
+-------------------------+-------------------------+
| innodb_version | 5.5.43 |
| protocol_version | 10 |
| slave_type_conversions | |
| version | 5.5.43-0ubuntu0.12.04.1 |
| version_comment | (Ubuntu) |
| version_compile_machine | x86_64 |
| version_compile_os | debian-linux-gnu |
+-------------------------+-------------------------+
7 rows in set (0.04 sec)
Thanks for any help.
The answers to both of your questions:
The first solution is slower than the second because in the first solution a new random value is calculated for every record, while in the second solution it's calculated only for the records needed to find one match. Also note that the condition for the second solution is much less strict.
You can have multiple return values in the first solution because a new random value is calculated for every record, and you don't have a limit statement. By the same logic, you could also have 0 results.
Take a look at this answer for a better solution.
I have a table named testing which contains a column with MEDIMTEXT type.
mysql> desc testing;
+-------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| id | tinyint(4) | YES | | NULL | |
| data | mediumtext | YES | | NULL | |
+-------+------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
And the table content is like--
mysql> select * from testing;
+------+--------------------------------+
| id | data |
+------+--------------------------------+
| 1 | This is the first data entered.|
+------+--------------------------------+
1 row in set (0.00 sec)
In the column named data in id=1, I want to concatenate another string ex- " Concat me " to make it look like "This is the first data entered. Concat me"
I could do it by using
UPDATE testing SET data=CONCAT(data,'Concat me') WHERE id=1;
but I think it would make the whole field to be read first, then concatenation, and in the end replacing the new made String to the previous one. In case if the text is too long, it would take a lot of time to do so.
like- if there is 15 MB of text and 10 bytes of text to concat, then 15 mb would be read, then 10 bytes of data concatenated and then 15 MB+ 10 bytes of data written back.
I want to ask that does there exist any other method so that the string to be concatenate is just added in the end instead of replacing the complete?
so that only 10 bytes are written in database.
May be I am wrong and mysql will manage the command to make it work efficiently.
Your update statement is perfectly fine. If you have an index in your data column then yes your update might be slower, in which case you could disable the index or remove it before update and add it back after your update completes.
I have a table which stores times as a simple varchar, in a format that looks like "2012-03-27T03:03:00".
I'd like to use mysql's date functions with this data. Some functions work fine, i.e.
mysql> select year('2012-03-14T11:28:32'), month('2012-03-14T11:28:32');
+-----------------------------+------------------------------+
| year('2012-03-14T11:28:32') | month('2012-03-14T11:28:32') |
+-----------------------------+------------------------------+
| 2012 | 3 |
+-----------------------------+------------------------------+
1 row in set (0.00 sec)
But hour and minute functions fail:
mysql> select hour('2012-03-14T11:28:32'), minute('2012-03-14T11:28:32');
+-----------------------------+-------------------------------+
| hour('2012-03-14T11:28:32') | minute('2012-03-14T11:28:32') |
+-----------------------------+-------------------------------+
| 0 | 20 |
+-----------------------------+-------------------------------+
1 row in set, 2 warnings (0.00 sec)
I believe it is the 'T' in my date format that screws up mysql. If I manually replace it with a space, the functions work:
mysql> select hour('2012-03-14 11:28:32'), minute('2012-03-14 11:28:32');
+-----------------------------+-------------------------------+
| hour('2012-03-14 11:28:32') | minute('2012-03-14 11:28:32') |
+-----------------------------+-------------------------------+
| 11 | 28 |
+-----------------------------+-------------------------------+
1 row in set (0.00 sec)
Is there some simple way I can tell mysql to parse the 'T'???
Those MySQL Date and Time functions (HOUR, for example) require a specific part of the timestamp.
Therefore, you need to use TIME and DATE to extract the time and date, respectively, from the passed timestamp:
Extracting the time:
select hour(time('2012-03-14T11:28:32')), minute(time('2012-03-14T11:28:32'));
Extracting the date:
select year(date('2012-03-14T11:28:32')), month(date('2012-03-14T11:28:32'));
SELECT HOUR(STR_TO_DATE('2012-03-14T11:28:32','%Y-%m-%dT%k:%i:%s'))
STR_TO_DATE is pretty good about returning NULL for rubbish dates like this non-leap-year item.
SELECT STR_TO_DATE('2011-02-29T11:28:32','%Y-%m-%dT%k:%i:%s')
It also lets you do stuff like
SELECT STR_TO_DATE('2011-02-28T11:28:32','%Y-%m-%dT%k:%i:%s') + INTERVAL 1 QUARTER
or
SELECT STR_TO_DATE('2011-02-28T11:28:32','%Y-%m-%dT%k:%i:%s') - INTERVAL 35 MINUTE
and have everything work right.
See here for the conversion specifiers.
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-format