MySQL get the date n days ago as a timestamp - mysql

In MySQL, how would I get a timestamp from, say 30 days ago?
Something like:
select now() - 30
The result should return a timestamp.

DATE_SUB will do part of it depending on what you want
mysql> SELECT DATE_SUB(NOW(), INTERVAL 30 day);
2009-06-07 21:55:09
mysql> SELECT TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 day));
2009-06-07 21:55:09
mysql> SELECT UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 day));
1244433347

You could use:
SELECT unix_timestamp(now()) - unix_timestamp(maketime(_,_,_));
For unix timestamps or:
SELECT addtime(now(),maketime(_,_,_));
For the standard MySQL date format.

If you need negative hours from timestamp
mysql>SELECT now( ) , FROM_UNIXTIME( 1364814799 ) , HOUR( TIMEDIFF( now( ) , FROM_UNIXTIME( 1364814799 ) ) ) , TIMESTAMPDIFF( HOUR , now( ) , FROM_UNIXTIME( 1364814799 ) )
2013-06-19 22:44:15 2013-04-01 14:13:19 1904 -1904
this
TIMESTAMPDIFF( HOUR , now( ) , FROM_UNIXTIME( 1364814799 ) )
will return negative and positive values, if you need to use x>this_timestamp
but this
HOUR( TIMEDIFF( now() , FROM_UNIXTIME( 1364814799 ) ) )
will return only positive, hours

Related

Mysql : finding data in last 24 hours query shows wrong results

I am executing the following query
SELECT post_expiredate
FROM tbl_postad
WHERE post_expiredate > DATE_SUB( CURDATE( ) , INTERVAL 1
DAY )
LIMIT 0 , 30
what I expect is, it should show the post_expiredate column with date values within last 24 hours. but it shows the wrong result
Please help me solve this issue
I tried
SELECT post_expiredate
FROM tbl_postad
WHERE DATE( post_expiredate ) > DATE( DATE_SUB( CURDATE( ) , INTERVAL 1
DAY ) )
also this
SELECT post_expiredate
FROM tbl_postad
WHERE post_expiredate > DATE_SUB( NOW( ) , INTERVAL 1
DAY )
but it also shows wrong date/
you did
WHERE post_expiredate > DATE_SUB( NOW( ) , INTERVAL 1
DAY )
which is wrong and list out all dates which are greater than yesterday
you need to find all post between yesterday and today
SELECT post_expiredate
FROM tbl_postad
WHERE post_expiredate between DATE_SUB( now( ) , INTERVAL 1
DAY ) and now()
SELECT post_expiredate
FROM tbl_postad
WHERE DATE(post_expiredate) BETWEEN CURDATE() + INTERVAL 1 DAY AND CURDATE()
this query must show all the "post_expiredate" between today and tomorrow.
Hope it helped.

how to add hours and minutes in curdate mysql

I am using date_add function to add 12 hours and 30 minutes in current date.
select DATE_ADD( CURDATE( ) , INTERVAL '12:30' HOUR_MINUTE )
gives me 2016-01-03 12:30:00
I just need date after adding 12:30.
what is the correct way to do same?
Just use the date function:
select DATE(DATE_ADD( CURDATE( ) , INTERVAL '12:30' HOUR_MINUTE ))
You can also express the logic using ADDTIME():
SELECT DATE(ADDTIME(currdate(), TIME('12:30:00')))
use NOW
SELECT DATE_ADD( now( ) , INTERVAL '12:30' HOUR_MINUTE )

SQL exception Parameter index out of range

I'm sending 4 values for the sql query through a jaggery script. Here is the sql query:
SELECT full_name , sum( amount ) AS total
FROM hourlyusage , user
WHERE DAY = DATE( DATE_SUB( NOW( ) , INTERVAL ? HOUR ) )
AND HOUR BETWEEN HOUR( DATE_SUB( NOW( ) , INTERVAL ? HOUR ) )
AND HOUR( DATE_SUB( NOW( ) , INTERVAL 1 HOUR ) )
AND hourlyusage.userIp = user.ip_address
AND (user.full_name LIKE '%?%' OR user.user_name LIKE '%?%') GROUP BY full_name
But it gives an exception like this.
Nested Exception:-
java.sql.SQLException: Parameter index out of range (3 > number of parameters, which is 2).
What would be the reason for that?
SELECT full_name , sum( amount ) AS total
FROM hourlyusage , user
WHERE DAY = DATE( DATE_SUB( NOW( ) , INTERVAL ? HOUR ) )
AND HOUR BETWEEN HOUR( DATE_SUB( NOW( ) , INTERVAL ? HOUR ) )
AND HOUR( DATE_SUB( NOW( ) , INTERVAL 1 HOUR ) )
AND hourlyusage.userIp = user.ip_address
AND (user.full_name LIKE ? OR user.user_name LIKE ?) GROUP BY full_name
You cannot use wildcard in the sql query so try to remove the wildcard from the sql and add it to the value.As you have done '%?%' in sql says that you need global match.Do that in your value not in sql query.

Issue with SQL getting Upcoming Birthdays

Can anyone fix the following SQL code, which gets upcoming birthdays:
SELECT *
FROM personal
WHERE 1 = ( FLOOR( DATEDIFF( DATE_ADD( DATE( NOW( ) ) , INTERVAL :interval DAY ) , dob ) / 365.25 ) ) -
( FLOOR( DATEDIFF( DATE_ADD( DATE( NOW( ) ) , INTERVAL -1 DAY ) , dob ) / 365.25 ) )
ORDER BY MONTH( dob ), DAY( dob )
LIMIT :rangeStart,:limit
It works aside from there is a bug with the ordering if the year rolls over. E.g. your in December checking ahead 1 month, then January birthday will get ordered before December.
I've seen a few posts on here about doing this, but none of them seem to get this part correct. I tried using the following ORDER BY clause, from another post and which seemed to work for someone else, but when I run it I get a syntax error:
ORDER BY ( MONTH(dob) > MONTH(NOW() OR ((MONTH(dob) = MONTH(NOW()) AND DAY(dob) >= DAY(NOW()) DESC, MONTH(dob), DAY(dob)
Updated answer ...
Thought of a cleaner way to accomplish this:
SELECT *
FROM (
SELECT *
,DATE_ADD( MAKEDATE( YEAR( NOW() ), DAYOFYEAR( dob ) )
,INTERVAL IF( DAYOFYEAR( dob ) < DAYOFYEAR( NOW() ), 1, 0 ) YEAR
)
AS next_birthday
FROM personal
) a
WHERE a.next_birthday < DATE_ADD( NOW(), INTERVAL :interval DAY )
ORDER BY a.next_birthday ASC
LIMIT :rangeStart,:limit
Explanation: next_birthday is calculated by taking this year's birthday and adding either 1 or 0 years to it depending on whether or not the birthday has already occurred this year - determined by IF( DAYOFYEAR( dob ) < DAYOFYEAR( NOW() ), 1, 0 ).
See it in action in SQLFiddle at http://sqlfiddle.com/#!9/b6471/1. Play with the number of days to see January after December.
Original answer ...
Add the following to your SELECT:
SELECT *
, CASE WHEN MAKEDATE( YEAR( CURRENT_DATE ), DAYOFYEAR( dob ) ) >= CURRENT_DATE
THEN MAKEDATE( YEAR( CURRENT_DATE ), DAYOFYEAR( dob ) )
ELSE DATE_ADD( MAKEDATE( YEAR( CURRENT_DATE ), DAYOFYEAR( dob ) ), INTERVAL 1 YEAR )
END AS next_birthday
then
ORDER BY next_birthday ASC
Rewriting your original query you get something like:
SELECT a.*
FROM ( SELECT *
, CASE WHEN DAYOFYEAR( dob ) >= DAYOFYEAR( CURRENT_DATE )
THEN MAKEDATE( YEAR( CURRENT_DATE ), DAYOFYEAR( dob ) )
ELSE DATE_ADD( MAKEDATE( YEAR( CURRENT_DATE ), DAYOFYEAR( dob ) ), INTERVAL 1 YEAR )
END AS next_birthday
FROM personal
) a
WHERE a.next_birthday < DATE_ADD( CURRENT_DATE, INTERVAL :interval DAY )
ORDER BY a.next_birthday ASC
LIMIT :rangeStart,:limit
I've now found a solution. For those that would like to know, the final code is:
SELECT *, DATE_ADD( dob, INTERVAL YEAR( FROM_DAYS( DATEDIFF( NOW( ), dob) -1 ) ) + 1 YEAR) AS next_birthday
FROM personal
WHERE 1 = ( FLOOR( DATEDIFF( DATE_ADD( DATE( NOW( ) ) , INTERVAL :interval DAY ) , dob ) / 365.25 ) ) -
( FLOOR( DATEDIFF( DATE_ADD( DATE( NOW( ) ) , INTERVAL -1 DAY ) , dob ) / 365.25 ) )
ORDER BY next_birthday ASC
LIMIT :rangeStart,:limit
I haven't tested it fully, but on simple tests it works.

Select time range from unix-timestamp

I have a MYSQL table with two columns, timestamp and span. timestamp is a unix-timestamp, while span is an integer.
I want to select all rows where the timestamp is between the current time +- half the span.
Eg. if the current time is 23:00, then I want all rows where the timestamp time is between 21 and 01. The issue is of-course that all the timestamps are from different days.
TO CLARIFY, I don't care about the date only the time
I've figured out a way to do this, but it seems like such a hack. I'm sure that someone with more MYSQL knowledge could show me a prettier way to do this.
SELECT *
FROM table
WHERE (
TIME( DATE_SUB( CURDATE( ) , INTERVAL( span /2 ) HOUR ) ) <= TIME( DATE_ADD( CURDATE( ) , INTERVAL( span /2 ) HOUR ) )
AND (
TIME( FROM_UNIXTIME( timestamp ) ) >= TIME( DATE_SUB( CURDATE( ) , INTERVAL( span /2 ) HOUR ) )
AND TIME( FROM_UNIXTIME( timestamp ) ) <= TIME( DATE_ADD( CURDATE( ) , INTERVAL( span /2 ) HOUR ) )
)
)
OR (
TIME( DATE_SUB( CURDATE( ) , INTERVAL( span /2 ) HOUR ) ) >= TIME( DATE_ADD( CURDATE( ) , INTERVAL( span /2 ) HOUR ) )
AND (
TIME( FROM_UNIXTIME( timestamp ) ) >= TIME( DATE_SUB( CURDATE( ) , INTERVAL( span /2 ) HOUR ) )
OR TIME( FROM_UNIXTIME( timestamp ) ) <= TIME( DATE_ADD( CURDATE( ) , INTERVAL( span /2 ) HOUR ) )
)
)
Two options I recommend.
Benchmark your "hack" query and see if that is faster than running two MySQL queries. Eg: One query to get your target row, another query to get results with ±1/2 span.
Write a proper MySQL stored procedure. This is effectively option (1) but all done inside the DB.
Another option I don't recommend, based on past pain, is to use MySQL variables to effectively do two selects avoiding the stored procedure, eg: http://dev.mysql.com/doc/refman/5.0/en/user-variables.html. This approach was common back in the old days of PHP/MySQL apps.
In my experience odds are good option (1) is both fast enough and readable.
Didn't really find a pretty solution, but this is how i ended up doing it.
SELECT *
FROM table
WHERE date_add( from_unixtime( timestamp ) , INTERVAL datediff( now( ) , from_unixtime( timestamp ) ) DAY )
BETWEEN date_sub( now( ) , INTERVAL (span/2) HOUR )
AND date_add( now( ) , INTERVAL (span/2) HOUR )
OR date_add( from_unixtime( timestamp ) , INTERVAL datediff( now( ) , from_unixtime( timestamp ) ) -1 DAY )
BETWEEN date_sub( now( ) , INTERVAL (span/2) HOUR )
AND date_add( now( ) , INTERVAL (span/2) HOUR )