Fetch data from last day, week, month and year in Mysql - mysql

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;

Related

Mysql dates of the last 30 days

I need help with some dates in mysql
I have this query that brings me the count of the messages of the corresponding dates of every message from the last 30 days.
SELECT DATE_FORMAT(time, '%m/%d/%Y') AS Dates, count(*) as count
FROM ma_messages
WHERE time BETWEEN NOW() - INTERVAL 30 DAY AND NOW()
AND usersid_send = 110
Group by Dates
ORDER BY Dates ASC
query image
But I need that also bring me the other dates of the last 30 days with a value in the count of 0, for example that in the query also bring me 05/26/2021 date and the dates before 05/25/2021 and after 05/28/2021.
I don't know if this is possible, but I will apreciate any help.
Thanks.
try this
SELECT
DATE_FORMAT(time, '%m/%d/%Y') AS Dates,
count(if(usersid_send='110',true,null)) as count
FROM ma_messages
WHERE time BETWEEN NOW() - INTERVAL 30 DAY AND NOW()
Group by Dates
ORDER BY Dates ASC
I have a table with dates .. with all the dates of the year – Alexis Murillo
SELECT d.`date`, COUNT(m.`time`) AS `count`
FROM dates_table d
LEFT JOIN ma_messages m ON d.`date` = DATE(m.`time`)
WHERE d.`date` BETWEEN NOW() - INTERVAL 30 DAY AND NOW()
AND m.usersid_send = 110
GROUP BY d.`date`
ORDER BY d.`date` ASC
Using your table "with all the dates of the year":
WITH
message_counts AS ( SELECT DATE_FORMAT("time", '%m/%d/%Y') AS "day",
COUNT(*) AS "count"
FROM ma_messages
WHERE "time" BETWEEN NOW() - INTERVAL 30 DAY AND NOW()
AND
usersid_send = 110
GROUP BY Dates)
SELECT all_dates."day", COALESCE(message_counts."count", 0)
FROM all_dates
LEFT JOIN message_counts
ON all_dates."day" = message_counts."day"
WHERE all_dates."day" BETWEEN BETWEEN NOW() - INTERVAL 30 DAY AND NOW()
ORDER BY all_dates."day" ASC

Add months in db date using interval in mysql

I want to add month in transaction date using mysql interval function by join plan table and transaction table,however this method not working but If I add months in static way to transaction date it is working.
plan table:
plan_id plan
1 6 month
2 12 month
3 3 month
transaction table:
id user_id subscribed_on plan_id
1 2 2020-04-04 1
2 4 2019-02-22 2
Mysql query (not working):
SELECT t.* FROM transaction t inner join plan p on p.plan_id=t.plan_id
where t.user_id=2 and DATE_ADD(date(t.subscribed_on), INTERVAL p.plan) >= CURDATE()
order by t.id desc
If I add month in static way than it is working fine:
SELECT t.* FROM transaction t inner join plan p on p.plan_id=t.plan_id
where t.user_id=2 and DATE_ADD(date(t.subscribed_on),
INTERVAL 6 month) >= CURDATE()
order by t.id desc
MySQL does not support using interval that way. Unlike in other databaes (such as Postgres for example), the unit argument is a keyword, not a literal string.
I would suspect that your table may store other intervals than just months (say, years, days, and so on). If so, you can use string functions and a case expression to accommodate the different possible values, like:
select t.*
from transaction t
inner join plan p on p.plan_id = t.plan_id
where
t.user_id = 2
and date(t.subscribed_on) + case substring_index(p.plan, ' ', -1)
when 'year' then interval substring_index(p.plan, ' ', 1) year
when 'month' then interval substring_index(p.plan, ' ', 1) month
when 'day' then interval substring_index(p.plan, ' ', 1) day
end
>= current_date
order by t.id desc
The logic here is to split the stored interval string into two parts: the number, and the unit; the case expression processes the unit and generate the proper literal interval accordingly.
Unfortunately a string in the data is not equivalent to an interval. One method is:
date(t.subscribed_on) + interval substring_index(plan, ' ') + 0 month
Note here that month is a keyword, not a string.
Try to force the plan column in the plan table to be an integer. Does not seem to be possible to cast a string to an interval.
I tried like so:
WITH
plan( plan_id,plan) AS (
SELECT 1,'6 month'
UNION ALL SELECT 2,'12 month'
UNION ALL SELECT 3,'3 month'
)
,
transaction(id,user_id,subscribed_on,plan_id) AS (
SELECT 1,2,DATE '2020-09-04',1
UNION ALL SELECT 2,4,DATE '2019-02-22',2
)
SELECT t.*
FROM transaction t
INNER JOIN plan p ON p.plan_id = t.plan_id
WHERE t.user_id = 2
AND DATE_ADD(
DATE(t.subscribed_on)
, INTERVAL CAST(REPLACE(plan,' month','') AS SIGNED) MONTH
) >= CURDATE()
ORDER BY t.id DESC
(returns no results, as you don't have any dates high enough in your example data...)

date_trunc PostgreSQL function equal for mySQL

Im trying to retrieve data to make statistics, im using mySQL and i cant get the following function to work - the postgreSQL is working.
I want to retrieve the request for the last month and count the amount of new requests for each day.
postgreSQL
SELECT count(*), date_trunc('day', created_at) as date FROM requests
WHERE(created_at > '2014-08-13 00:00:00') GROUP BY 2 ORDER BY 2 ASC;
*mySQL - my code *
SELECT count(EXTRACT(DAY FROM created_at)), EXTRACT(DAY FROM created_at) as date
FROM `requests`
WHERE EXTRACT(DAY FROM NOW() - INTERVAL 1 MONTH)
GROUP BY date
Final code
SELECT count( * ) , date( created_at ) AS date
FROM `requests`
WHERE DATE( created_at ) > DATE( DATE_SUB( NOW( ) , INTERVAL 1 MONTH ) )
GROUP BY date
The equivalent for your case is date():
select date(created_at), count(*)
from requests
. . .
This isn't a general replacement, but it works to remove the time portion of a date.
EDIT:
Perhaps the better solution for these two databases is:
select cast(created_at as date)
This is ANSI standard and works in both these databases (as well as SQL Server). I personally don't use this in general, lest I accidentally use it in Oracle, causing difficult to find errors. (dates in Oracle have a time component, alas.)

Mysql subtracting values using row selected from min timestamp, grouping by id

I've been at this for a few hours now to no avail, pulling my hair out.
Edit: Im wanting to calculate the difference between the overall_exp column by using the same data from 1 day ago to calculate the greatest 'gain' for each user
Currently I'm take a row, then select a row from 1 day ago based on the first rows timestamp then subtract the overall_exp column from the 2 rows and order by that result whilst grouping by user_id
SQL Fiddle: http://sqlfiddle.com/#!2/501c8
Here is what i currently have, however the logic is completely wrong so im pulling 0 results
SELECT rsn, ts.timestamp, #original_ts := SUBDATE( ts.timestamp, INTERVAL 1 DAY), ts.overall_exp, ts.overall_exp - previous.overall_exp AS gained_exp
FROM tracker AS ts
INNER JOIN (
SELECT user_id, MIN( TIMESTAMP ) , overall_exp
FROM tracker
WHERE TIMESTAMP >= #original_ts
GROUP BY user_id
) previous
ON ts.user_id = previous.user_id
JOIN users
ON ts.user_id = users.id
GROUP BY ts.user_id
ORDER BY gained_exp DESC
You can do this with a self-join:
select t.user_id, max(t.overall_exp - tprev.overall_exp)
from tracker t join
tracker tprev
on tprev.user_id = t.user_id and
date(tprev.timestamp) = date(SUBDATE(t.timestamp, INTERVAL 1 DAY))
group by t.user_id
A key here is converting the timestamps to dates, so the comparison is exact.
Try:
select u.*, max(t.`timestamp`)-min(t.`timestamp`) gain
from users u
left join tracker t
on u.id = t.user_id and
t.`timestamp` >= date_sub(date(now()), interval 1 day) and
t.`timestamp` < date_add(date(now()), interval 1 day)
group by u.id
order by gain desc
SQLFiddle here.

Average posts per hour on MySQL?

I have a number of posts saved into a InnoDB table on MySQL. The table has the columns "id", "date", "user", "content". I wanted to make some statistic graphs, so I ended up using the following query to get the amount of posts per hour of yesterday:
SELECT HOUR(FROM_UNIXTIME(`date`)) AS `hour`, COUNT(date) from fb_posts
WHERE DATE(FROM_UNIXTIME(`date`)) = CURDATE() - INTERVAL 1 DAY GROUP BY hour
This outputs the following data:
I can edit this query to get any day I want. But what I want now is the AVERAGE of each hour of every day, so that if on Day 1 at 00 hours I have 20 posts and on Day 2 at 00 hours I have 40, I want the output to be "30". I'd like to be able to pick date periods as well if it's possible.
Thanks in advance!
You can use a sub-query to group the data by day/hour, then take the average by hour across the sub-query.
Here's an example to give you the average count by hour for the past 7 days:
select the_hour,avg(the_count)
from
(
select date(from_unixtime(`date`)) as the_day,
hour(from_unixtime(`date`)) as the_hour,
count(*) as the_count
from fb_posts
where `date` >= unix_timestamp(current_date() - interval 7 day)
and created_on < unix_timestamp(current_date())
group by the_day,the_hour
) s
group by the_hour
Aggregate the information by date and hour, and then take the average by hour:
select hour, avg(numposts)
from (SELECT date(`date`) as day, HOUR(FROM_UNIXTIME(`date`)) AS `hour`,
count(*) as numposts
from fb_posts
WHERE DATE(FROM_UNIXTIME(`date`)) between <date1> and <date2>
GROUP BY date(`date`), hour
) d
group by hour
order by 1
By the way, I prefer including the explicit order by, since most databases do not order the results of a group by. Mysql happens to be one database that does.
SELECT
HOUR(FROM_UNIXTIME(`date`)) AS `hour`
, COUNT(`id`) \ COUNT(DISTINCT TO_DAYS(`date`)) AS avgHourlyPostCount
FROM fb_posts
WHERE `date` > '2012-01-01' -- your optional date criteria
GROUP BY hour
This gives you a count of all the posts, divided by the number of days, by hour.