A user can get at max 5 reports before i ban him for 1 day from the chat, when row from this user reach 5 reports i store a date on the row, and i can unban him after 1 day with the sql data < DATE_SUB(NOW(), INTERVAL 1 DAY).
But this way he is not able to be "unbanned" from the chat, if he does not loggin on their account until 47:99 hours, because the INTERVAL 1 DAY will not work. So how can i make a WHERE clause to match a row that is at least 1 DAY ago or that is >= 1 DAY ago? It's possible?
$link_id = $_SESSION['linkN'];
$deletReport = $conn->prepare("DELETE FROM `report_public_chat` WHERE `link_id` = :link_id AND `data` < DATE_SUB(NOW(), INTERVAL 1 DAY)");
$deletReport->bindParam(":link_id", $link_id, PDO::PARAM_INT);
$deletReport->execute();
Use delete condition like
WHERE date >= now() - INTERVAL 1 DAY;
OR
WHERE timediff(now(), my_datetime_field) < '24:00:00'
You can try below - using DATE_SUB(NOW(), INTERVAL 24 hours)
DELETE FROM `report_public_chat` WHERE `link_id` = :link_id AND `data` >= DATE_SUB(NOW(), INTERVAL 24 hours) and `data`<NOW()
Related
I have a table with the following data:
I am looking to group the rows into the following:
Within the last day (everything within the last 24 hours)
Within the last 7 days (everything within the last week)
Within the last 30 days (everything within the last month)
The end result for the above rows would look something like:
I can group the records into these brackets right now with:
SELECT (CASE WHEN created_at = CURDATE() THEN '1 Day'
WHEN created_at >= CURDATE() - INTERVAL 6 DAY THEN '7 Days'
WHEN created_at >= CURDATE() - INTERVAL 29 DAY THEN '30 Days'
END) AS Timeframe, COUNT(*) AS Count
FROM my_table
GROUP BY (CASE WHEN created_at = CURDATE() THEN '1 Day'
WHEN created_at >= CURDATE() - INTERVAL 6 DAY THEN '7 Days'
WHEN created_at >= CURDATE() - INTERVAL 29 DAY THEN'30 Days'
END)
But this will prevent individual records from being counted more than once. For example, lines 2 and 3 in the first picture needs to be counted in all three brackets (1 day, 7 days, and 30 days) - while lines 6 through 9 only needs to be counted in the 30 days bracket.
How would you do this with MySQL?
It is easiest to do this as columns, rather than rows:
SELECT SUM(created_at = CURDATE()) as today
SUM(created_at >= CURDATE() - INTERVAL 6 DAY) as last_7_days,
SUM(created_at >= CURDATE() - INTERVAL 29 DAY) as last_30_days,
SUM(created_at < CURDATE() - INTERVAL 29 DAY) as older
FROM my_table;
If you want your response in several rows, instead of just one with several columns, take #Gordon Linoff as your starting point... but perform the queries "one row at at time" (it won't be as efficient, because you visit the table 4 times instead of 1!):
-- Row for the 1 day timeframe
SELECT '1 Day' AS `Timeframe`, SUM(created_at = CURDATE()) AS `Count`
FROM my_table
UNION
-- Row for the 7 days timeframe...
SELECT '7 Days' AS `Timeframe`, SUM(created_at >= CURDATE() - INTERVAL 6 DAY) AS `Count`
FROM my_table
UNION
SELECT '30 Days' AS `Timeframe`, SUM(created_at >= CURDATE() - INTERVAL 29 DAY) AS `Count`
FROM my_table
UNION
SELECT 'Older' AS `Timeframe`, SUM(created_at < CURDATE() - INTERVAL 29 DAY) AS `Count`
FROM my_table ;
If you can use MariaDB instead of MySQL, you can use a WITH, which will allow the query to be efficient again:
WITH stats AS
(
SELECT SUM(created_at = CURDATE()) as today,
SUM(created_at >= CURDATE() - INTERVAL 6 DAY) as last_7_days,
SUM(created_at >= CURDATE() - INTERVAL 29 DAY) as last_30_days,
SUM(created_at < CURDATE() - INTERVAL 29 DAY) as older
FROM my_table
)
-- Convert to rows with negligible overhead
SELECT '1 Day' AS `Timeframe`, today FROM stats
UNION
SELECT '7 Days', last_7_days FROM stats
UNION
SELECT '30 Days', last_30_days FROM stats
UNION
SELECT 'Older', older FROM stats ;
In both cases, you'll get (as of 2017-07-25):
Timeframe | today
:-------- | ----:
1 Day | 0
7 Days | 4
30 Days | 8
Older | 0
dbfiddle here
SELECT COUNT(*) FROM `table` WHERE `datetime` > SUBDATE(NOW(), INTERVAL 1 DAY)
This will get number of entries during last day. But is it possible to get number of entries for multiple intervals without having to send variation of this query multiple times (INTERVAL 1 DAY, INTERVAL 1 WEEK, INTERVAL 1 MONTH, ...)?
You need CASE WHEN expression to accomplish that.
SELECT
COUNT(CASE WHEN DATE(`datetime`) >= CURDATE() - INTERVAL 1 DAY AND DATE(`datetime`) < CURDATE() THEN 1 END) AS lastDay,
COUNT(CASE WHEN DATE(`datetime`) >= CURDATE() - INTERVAL 7 DAY AND DATE(`datetime`) < CURDATE() THEN 1 END ) AS lastSevenDays,
COUNT(*) AS lastThirtyDays
FROM `table`
WHERE
DATE(`datetime`) >= CURDATE() - INTERVAL 30 DAY
How to use CASE WHEN expression
Note: If your requirement is to get result of last day, last 7 days and last 30 days then go with this query.
EDIT:
If you have an index on datetime field then the above query will fail to use that index. Please use the query given below in order to utilize the index on datetime.
SELECT
COUNT(CASE WHEN DATE(`datetime`) >= CURDATE() - INTERVAL 1 DAY AND DATE(`datetime`) < CURDATE() THEN 1 END) AS lastDay,
COUNT(CASE WHEN DATE(`datetime`) >= CURDATE() - INTERVAL 7 DAY AND DATE(`datetime`) < CURDATE() THEN 1 END ) AS lastSevenDays,
COUNT(*) AS lastThirtyDays
FROM `table`
WHERE
`datetime` >= (NOW() - INTERVAL 30 DAY - INTERVAL HOUR(NOW()) HOUR - INTERVAL MINUTE(NOW()) MINUTE - INTERVAL SECOND(NOW()) SECOND)
I'm trying to structure a query which returns data which if priority = emergency is in the last 2 weeks, and if urgent is in the last month.
WHERE ((priority = 'emergency' and date > DATE_SUB(NOW(), INTERVAL 14 DAY)) or
priority = 'urgent' and date > DATE_SUB(NOW(), INTERVAL 30 DAY))
I know this isn't right, but I'm not sure how to do it.
It just looks like your parentheses are in the wrong place:
WHERE ( priority = 'emergency' and date > DATE_SUB(NOW(), INTERVAL 14 DAY) )
OR ( priority = 'urgent' and date > DATE_SUB(NOW(), INTERVAL 30 DAY) )
Since not all months are 30 days you might have to adjust the interval if you want strictly one month back.
here is the code I am using to return past 24 hours records
SELECT *
FROM mytable
WHERE CASE WHEN `created` > DATE_SUB(NOW(), INTERVAL 1 DAY) THEN 1 ELSE 0 END
how to return records between yesterday and last 7 days
Use the BETWEEN operator.
CASE WHEN created BETWEEN DATE_SUB(NOW(), INTERVAL 7 DAY) AND DATE_SUB(NOW(), INTERVAL 1 DAY)
THEN 1
ELSE 0
END
Try this, it works without case statement, so should be faster:
SELECT *
FROM mytable
WHERE created BETWEEN date(CURRENT_TIMESTAMP-7) AND date(CURRENT_TIMESTAMP-1);
startTimestamp < date_sub(curdate(), interval 1 hour)
Will the (sub)query above return all records created within the hour? If not will someone please show me a correct one? The complete query may look as follows:
select * from table where startTimestamp < date_sub(curdate(), interval 1 hour);
Rather than CURDATE(), use NOW() and use >= rather than < since you want timestamps to be greater than the timestamp from one hour ago. CURDATE() returns only the date portion, where NOW() returns both date and time.
startTimestamp >= date_sub(NOW(), interval 1 hour)
For example, in my timezone it is 12:28
SELECT NOW(), date_sub(NOW(), interval 1 hour);
2011-09-13 12:28:53 2011-09-13 11:28:53
All together, what you need is:
select * from table where startTimestamp >= date_sub(NOW(), interval 1 hour);