Date Interval Bug - mysql

I have a table which has a column called created DATETIME, When adding entries It works fine, but when It gets to Date Interval, It keeps on duplicating new entries. I'm trying to get Today's and Yesterday's entries. Today's works fine, but for Yesterday's, It also puts on Today's contents in query results which Is not what I want.
SELECT * FROM tab WHERE created > DATE_SUB(NOW(), INTERVAL $num DAY) ORDER BY created DESC LIMIT 9;
$num Is 1 for Today's entries, and It's 2 for Yesterday's. So basically an entry which Is created today, Is getting duplicated on Yesterday's query results.

You are getting the results you requested from the database. Namely any record that is greater than today minus however many days you put in.
The reason you get 0 records when you try #KenWhite's suggested of changing your > to = is because your field is DATETIME, so subtracting exactly 24 hours from NOW() yields the same exact time yesterday and you probably don't have a record that was written precisely at this time yesterday. Right?
What you'll have to do is test for records between two dates to get you want. Instead of NOW(), switch to CURDATE(), this way you can be assured you'll get every record for the datetime range you are looking for.
SELECT *
FROM tab
WHERE
created BETWEEN DATE_SUB(CURDATE(), INTERVAL $num DAY) AND DATE_SUB(CURDATE(), INTERVAL $num - 1 DAY)
ORDER BY created DESC LIMIT 9;
You can check out a SQLFiddle of this here: http://sqlfiddle.com/#!2/19d9b/12

With datetime/timestamp values, similar to floats, always use ranges with closed beginnings and open endings. So use '>=' and '<'.
For example to use the data of a single day:
SELECT ... FROM tab
WHERE created >= CURDATE() - INTERVAL #num:=? DAY
AND created < CURDATE() - INTERVAL #num DAY + INTERVAL 1 DAY
ORDER BY created DESC
LIMIT 9
;
With MySQL, generally prefer the timestamp type over the datetime type, as datetime doesn't carry timezone information.
Alternatives:
created_at timestamp NULL DEFAULT NULL COMMENT 'set by application',
created_at timestamp NOT NULL DEFAULT '1970-01-01 23:00:00' COMMENT 'set by application',
dbms_row_created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'set by DBMS',

Related

sum elements of json column postgres

I'm trying to sum all my elements of a specific type in a json column of the last 24 hours and I can't figure out my query.
So I have a json column called data and i want the "live" key to have the sum of all "live" in the last 24 hours and for that I was trying to do something like this
select sum(data->>'live'::json)
from probing
where device_id='f051b333-8f1f-4e65-9acc-e76470a87f47'
and timestamp > current_timestamp - interval '1 day'
order by timestamp desc;
I know this doesn't work and I can't figure a viable solution to this. I saw some solutions including using "json_array_elemens" or "json_each" but can't make this work.
I came with this solution:
select
sum(cast(data->>'live' as integer))
from
probing
where
device_id='f051b333-8f1f-4e65-9acc-e76470a87f47'
and timestamp > current_timestamp - interval '1 day';
U can query in both the ways:
select sum((data->>'live')::int)
from probing
where device_id='f051b333-8f1f-4e65-9acc-e76470a87f47'
and timestamp > current_timestamp - interval '1 day'
order by timestamp desc;
select sum(cast(data->>'live' as int))
from probing
where device_id='f051b333-8f1f-4e65-9acc-e76470a87f47'
and timestamp > current_timestamp - interval '1 day'
order by timestamp desc ;

Value of time of the beginning of today

I am trying to get the number of times a user has logged in since the beginning of each day.
SELECT user_id
FROM users
WHERE TIMESTAMPDIFF(HOUR, user_login, NOW()) < 12
AND user_id = 1
This sql checks the difference between the login and the current time which is wrong.
What should go instead of NOW() to indicate midnight+1min of that day and check the logins throughout that day?
As far as I understand your code, the question is rather about mySQL and not PHP. Use
CURDATE()
instead of NOW() since TIMESTAMPDIFF will use this as 'Current Day, 00:00:00'
To get the end of the current day use
CURDATE() + INTERVAL 1 DAY
so your where-clause should be
WHERE user_login BETWEEN CURDATE() AND CURDATE() + INTERVAL 1 DAY
provided you have the user_login field in the DATE format, otherwise you would have to cast that accordingly.

How can I get the date difference of a timestamp

I am trying to create a query that will limit insertion into a table based on the last time the poster sent data to the table.
For example if you posted data to the table then you are locked out of the system for another 10 hours. Here is what I came up with so far. But I get nowhere with the actual results on the data. Any help?
SELECT DATE( `date` )
FROM tablename
WHERE DATE( CURDATE( ) ) < CURDATE( ) - INTERVAL 1002
DAY
LIMIT 0 , 30
This will return a single post from the last 10 hours, if it exists:
SELECT *
FROM tablename
WHERE `date` >= NOW() - INTERVAL 10 HOUR
LIMIT 1
I'm assuming date is declared as DATETIME, since actual DATE does not contain the time part and hence is only day-accurate.
If date is an integer UNIX timestamp, use this:
SELECT *
FROM tablename
WHERE `date` >= UNIX_TIMESTAMP(NOW() - INTERVAL 10 HOUR)
LIMIT 1
There are a number of ways you could do this. Perhaps if you have a user settings table you could simply add a "last_insert" field, and store the timestamp as an integer value- that would be a super simple way to do it- you could check the current timestamp vs user_settings.last_insert and voila!
I suppose you could use datetime too. Whatever floats the boat.
First of all, you need a DATETIME column and not a DATE column. Assuming that tablename.date is a DATETIME column, then 10 hours before right now is CURRENT_TIMESTAMP - INTERVAL 10 HOUR.
First of all create a Time (TIMESTAMP DEFAULT CURRENT_TIMESTAMP) columnt in your table. It will be automatically set to current date on row insert
Then check:
SELECT COUNT(*) FROM Table WHERE Time > NOW() - INTERVAL 10 HOUR
If its 1 or more - block
You must compare the time last post was put with current time, not current time with current time :|

Grouping timestamp field by date

I am trying to write an SQL query to return how many links were submitted to my website over the last 7 day period. So far I have this:
SELECT COUNT(`id`) AS `count`
FROM `links`
WHERE `created` > NOW() - 86400
AND `created` < NOW()
this works for one day, it returns one row called count with the number of links submitted in the last 24 hours. I need to change it to return 2 columns called date and count, with 7 rows (one for each day).
The tricky part that I can't get my head around is that created is a timestamp column, and I don't have access to change it so I have to work with it.
Edit: work in progress for the query:
SELECT DAY(FROM_UNIXTIME(created)) AS day, COUNT(id) count
FROM links
GROUP BY DAY(FROM_UNIXTIME(created))
LIMIT 7
NOW() actually shouldn't be working as it returns a datetime. Also, if you want to fetch 7 days worth of data, you want to subtract 604800 from UNIX_TIMESTAMP(). You can use then date and time functions with FROM_UNIXTIME. This will make grouping easier. Optimally, your column should be of datetime type.
It would go something like:
SELECT DAY(FROM_UNIXTIME(created)) day, COUNT(id) count
FROM links
WHERE created > UNIX_TIMESTAMP() - 604800 AND created < UNIX_TIMESTAMP()
GROUP BY DAY(FROM_UNIXTIME(created))
You can alternatively use the BETWEEN operator:
WHERE created BETWEEN UNIX_TIMESTAMP() - 604800 AND UNIX_TIMESTAMP()
See the demo

getting mysql dates 3 days earlier when all dates in timestamp format

I have all dates stored as timestamps (int) in the database.
how can I get dates that are exactly 3 days earlier?
I tried
SELECT date from user WHERE DATE_ADD(DATE( FROM_UNIXTIME( `created` ) ), INTERVAL 3 DAY) = CURDATE()
is that the best/most efficient way to do it?
i think the database prefer to only do the date add 2 times to define the range, like:
SELECT date FROM user
WHERE UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL -3 DAY)) <= `created`
AND `created` < UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL -2 DAY));
Test putting DESCRIBE keyword before SELECT in both case, and the database respond with how its going to perform the query
SELECT date
FROM user
WHERE created = UNIX_TIMESTAMP(CURRENT_DATE - INTERVAL 3 DAY)
Note: no function used on the created column in where clause. This query should be able to use index.