I have a datetime column called 'last_login'.
I want to query my database to select all records that haven't logged in within the last month. How do I do this?
This is what I have currently:
$query = $this->query("SELECT u.id, u.name, u.email, u.registered, g.name as group_name FROM `:#users` AS u LEFT JOIN `:#groups` AS g on u.group_id = g.id WHERE u.last_login = ...... LIMIT {$limit_start}, {$limit_end}");
:# = database prefix
Try using date_sub
where u.last_login < date_sub(now(), interval 1 month)
(Similar to the first answer but in my mind it is more "natural" to use positive integers)
You can use date_add combined with now:
...where u.last_login < date_add(now(), interval -1 month)
Naturally, as both are MySQL-specific this limits you to MySQL backends. Alternately, you can figure out what the date was a month ago with PHP (I'm not a PHP person, but I'm guessing DateTime::sub would help with that) and then include that date in your query in the normal way you would any other date/time field.
matthewh was almost correct, except the > should have been a right one.
where u.last_login > date_sub(now(), interval 1 month)
Related
I am trying to add 5 days to a date in MYSQL in a query. This is what I have done:
SELECT * FROM sales INNER JOIN partner on user_id = idpartner WHERE DATE((end_date) + 5) >= DATE(NOW()) ORDER BY end_date ASC LIMIT 0,50000
But this is not showing the list of sales which has ended. Can someone please tell me where I am making a mistake.
It looks like you want rows where end_date is later than five days ago.
The best way to get that is with
WHERE end_date >= CURDATE() - INTERVAL 5 DAY
The business of adding integers to dates doesn't work in MySQL (it's an Oracle thing). So you need to use the INTERVAL n unit syntax.
You'll notice that my WHERE clause above is functionally equivalent to
WHERE DATE(end_date) + INTERVAL 5 DAY >= DATE(NOW())
But, the first formulation is superior to the second for two reasons.
if you mention end_date in a WHERE clause without wrapping it in computations, your query can exploit an index on that column and can run faster.
DATE(NOW()) and CURDATE() both refer to the first moment of today (midnight). But CURDATE() is a bit simpler.
To fix the original query, you can use DATE_ADD with the INTERVAL keyword:
SELECT
*
FROM
sales
INNER JOIN
partner ON user_id = idpartner
WHERE
DATE_ADD(end_date, INTERVAL 5 DAY) >= DATE(NOW())
ORDER BY end_date ASC
LIMIT 0 , 50000
Said that, I wouldn't recommend applying functions such as DATE_ADD on columns, as it means that the database won't be able to use an index on end_date. Therefore, I would modify the query to:
SELECT
*
FROM
sales
INNER JOIN
partner ON user_id = idpartner
WHERE
end_date <= DATE_ADD(DATE(NOW()), INTERVAL 5 DAY)
ORDER BY end_date ASC
LIMIT 0 , 50000
As you can see, in the second alternative all functions are applied on constants and not on columns (end_date).
You can try
DATE_ADD() here is the
Link
Select DATE_ADD(DATE_FORMAT(NOW(),'%Y-%m-%d'),INTERVAL 1 DAY) FROM DUAL
I read many topics to fetch data that posted in different periods, but as the Time in my mysql table is in STRING format I couldn't make it happen.
SELECT s.user_id, count(*) AS wins, u.username, u.avatar,u.avatar_uploaded
FROM on_scores AS s
LEFT JOIN on_users AS u ON (u.userid = s.user_id)
WHERE s.is_high = '1' AND DATE(s.date_score) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
GROUP BY s.user_id
ORDER BY wins DESC
LIMIT 10
I tried the STR_TO_DATE method but still no output.
Use the from_unixtime function to get the time into a date-like format.
More info here.
Information on formatting the resultant date - here.
Example:
select date_sub( from_unixtime( s.datescore ), INTERVAL 1 MONTH ) as monthfromdatevalue;
select datediff( from_unixtime( s.datescore, curdate()) as howlongago_fromtoday;
I have a table structure that looks like this:
I have a perfectly working query that counts how many records there have been per day the last 30 days. It looks likes this:
SELECT DATE(timestamp) AS date, COUNT(id) AS emails FROM 'emails WHERE timestamp >= now() - interval 1 month GROUP BY DATE(timestamp)
This outputs the following which is perfectly fine:
However, the next thing seems too difficult for me to imagine. Now I want to count how many records there have been per day the last 30 days BUT only where newsletter = 1.
I've tried to put a WHERE statement looking like this:
SELECT DATE(timestamp) AS date, COUNT(*) AS emails, nyhedsbrev FROM emails WHERE timestamp >= now() - interval 1 month AND nyhedsbrev = 1 GROUP BY DATE(timestamp)
... And that outputs the following:
The problem is, that its omitting the records with newsletter = 0 and there by I cant compare my first query against the new one, as the dates doesnt match. I know that is because I use WHERE newsletter = 1.
In stead of omitting the record I want a query that just puts a "0" from that date. How can I do this? The final query should be outputting this:
You should be able to simply use SUM() and IF() to get the desired output:
SELECT
DATE(timestamp) AS date,
COUNT(*) AS emails,
SUM(IF(nyhedsbrev > 0, 1, 0)) as nyhedsbrev_count
FROM
emails
WHERE
timestamp >= now() - interval 1 month
GROUP BY
DATE(timestamp)
SQLFiddle DEMO
Edit: You might even be able to simplify it, since it's a boolean, and simply use SUM(nyhedsbrev), but this REQUIRES that nyhedsbrev is only 0 or 1:
SELECT
DATE(timestamp) AS date,
COUNT(*) AS emails,
SUM(nyhedsbrev) as nyhedsbrev_count
FROM
emails
WHERE
timestamp >= now() - interval 1 month
GROUP BY
DATE(timestamp)
Possibly best to get a list of the dates and then left join that against sub queries to get the counts you require.
Something like this
SELECT Sub1.date, Sub2.emails, IFNULL(Sub3.emails, 0)
FROM (SELECT DISTINCT DATE(timestamp) AS date
FROM emails
WHERE timestamp >= now() - interval 1 month) Sub1
LEFT OUTER JOIN (SELECT DATE(timestamp) AS date, COUNT(id) AS emails
FROM emails WHERE timestamp >= now() - interval 1 month
GROUP BY DATE(timestamp)) Sub2
ON Sub2.date = Sub3.date
LEFT OUTER JOIN (SELECT DATE(timestamp) AS date, COUNT(*) AS emails
FROM emails
WHERE timestamp >= now() - interval 1 month AND nyhedsbrev = 1
GROUP BY DATE(timestamp)) Sub3
ON Sub1.date = Sub3.date
(you can probably optimise one subselect of this away, but I have done it in full to make it obvious how it is working)
Assuming newsletter is boolean 1/0 values then this might give you the table that you want:
SELECT DATE(timestamp) AS date, COUNT(*) AS emails, nyhedsbrev
FROM emails WHERE timestamp >= now() - interval 1 month GROUP BY DATE(timestamp),nyhedsbrev ;
Just adding another GROUP BY parameter.
I have saved the dates of a user's registration as a datetime, so that's for instance 2011-12-06 10:45:36. I have run this query and I expected this item - 2011-12-06 10:45:36 - will be selected:
SELECT `users`.* FROM `users` WHERE created_at >= '2011-12-01' AND
created_at <= '2011-12-06'
But is not. Exist any elegant way, how to select this item? As a first idea that I got was like 2011-12-06 + 1, but this doesn't looks very nice.
Your problem is that the short version of dates uses midnight as the default. So your query is actually:
SELECT users.* FROM users
WHERE created_at >= '2011-12-01 00:00:00'
AND created_at <= '2011-12-06 00:00:00'
This is why you aren't seeing the record for 10:45.
Change it to:
SELECT users.* FROM users
WHERE created_at >= '2011-12-01'
AND created_at <= '2011-12-07'
You can also use:
SELECT users.* from users
WHERE created_at >= '2011-12-01'
AND created_at <= date_add('2011-12-01', INTERVAL 7 DAY)
Which will select all users in the same interval you are looking for.
You might also find the BETWEEN operator more readable:
SELECT users.* from users
WHERE created_at BETWEEN('2011-12-01', date_add('2011-12-01', INTERVAL 7 DAY));
SELECT users.* FROM users WHERE created_at BETWEEN '2011-12-01' AND '2011-12-07';
You need to use '2011-12-07' as the end point as a date without a time default to time 00:00:00.
So what you have actually written is interpreted as:
SELECT users.*
FROM users
WHERE created_at >= '2011-12-01 00:00:00'
AND created_at <= '2011-12-06 00:00:00'
And your time stamp is: 2011-12-06 10:45:36 which is not between those points.
Change this too:
SELECT users.*
FROM users
WHERE created_at >= '2011-12-01' -- Implied 00:00:00
AND created_at < '2011-12-07' -- Implied 00:00:00 and smaller than
-- thus any time on 06
Another alternative is to use DATE() function on the left hand operand as shown below
SELECT users.* FROM users WHERE DATE(created_at) BETWEEN '2011-12-01' AND '2011-12-06'
Have you tried before and after rather than >= and <=? Also, is this a date or a timestamp?
Searching for created_at <= '2011-12-06' will search for any records that where created at or before midnight on 2011-12-06
. You want to search for created_at < '2011-12-07'.
Maybe use in between better. It worked for me to get range then filter it
You can use MySQL DATE function like below
For instance, if you want results between 2017-09-05 till 2017-09-09
SELECT DATE(timestamp_field) as date FROM stocks_annc WHERE DATE(timestamp_field) >= '2017-09-05' AND DATE(timestamp_field) <= '2017-09-09'
Make sure to wrap the dates within single quotation ''
Edit:
A better solution would be this. It would make sure that it uses the index if any exists.
select date(timestamp_field) as date from stocks_annc where time_stamp_field >= '2022-01-01 00:00:00' and time_stamp_field <= '2022-01-10 00:00:00'
Hope this helps.
I always have trouble with complicated SQL queries.
This is what I have
$query = '
SELECT id,
name,
info,
date_time
FROM acms_events
WHERE date_time = DATE_SUB(NOW(), INTERVAL 1 HOUR)
AND active = 1
ORDER BY date_time ASC
LIMIT 6
';
I want to get up to 6 rows that are upcoming within the hour. Is my query wrong? It does not seem to get events that are upcoming within the next hour when I test it.
What is the correct syntax for this?
I'm going to postulate that you're looking at a group of records that contain a range of DATETIME values, so you probably want something more like this:
SELECT id,
name,
info,
date_time
FROM acms_events
WHERE date_time < DATE_ADD(NOW(), INTERVAL 1 HOUR)
AND date_time >= NOW()
AND active = 1
ORDER BY date_time ASC
LIMIT 6
Otherwise, your query is looking for records with a date_time of exactly "now + 1 hour". I'm assuming all your dates aren't specific to that particular second. ;)
To clarify a bit, DATE_ADD() and DATE_SUB() return exact timestamps, so your query above roughly translates to something like SELECT ... WHERE date_time = '2010-04-14 23:10:05' ORDER BY ..., which I don't think is what you want.
WHERE date_time = DATE_SUB(NOW(), INTERVAL 1 HOUR)
means date_time equals exactly now minus one hour, which would result in any record exactly one hour old.
Why not use
WHERE TIMEDIFF(date_time, NOW()) < '01:00:00'
AND date_time > NOW()