Calculate the average number of hours in table per month - mysql

I have a table named "loginhistory", and I need to calculate the most active hour of the month. How can i do it?
My table structure is:
id, userId, date (datetime), ip.
I tried to do it in PHP but I did not succeed there either. I prefer the calculation to be done only in MySql.
I expect the output to be just the number of the most active hour.

It does not matter checking average number if needed to pick active hour.
Cause average = count / days and since days is the same for whole calculation (let's say 30) the greatest count will be active hour in list.
Just select by date range and group by hour and pick 1st one from descending sort:
SELECT
HOUR(date) AS hour,
COUNT(id) AS logins,
( COUNT(id) / DAY(LAST_DAY('2019-01-01')) ) AS logins_avg
FROM loginhistory
WHERE
date >= '2019-01-01 00:00:00' AND date < '2019-02-01 00:00:00'
GROUP BY HOUR(date)
ORDER BY logins DESC LIMIT 1

Related

MySQL grouping from complex query

I need to create a query that looks like this image with the result:
You can ignore the names of the user, user_id is fine for now. Each user can have several timesheets for one day. So I need to count the hours and place it in its own column for day of the week. Then have a total at the end. Here is a screen shot of the database:
Here is what I have so far that gets me the days of the week totals but not grouped in one record with the day of the week as its own column and a total. Any help would be appreciated. Thanks!
SELECT user_id, WEEKDAY(start_date) AS day, (select time_to_sec(timediff(end_date, start_date )) / 3600) AS hours FROM `timesheet_table` WHERE id > 0 GROUP BY day, user_id
If you need a totat you can use a sum and group by
In Group by you can't use the alias but you should use the expression
SELECT
user_id
, WEEKDAY(start_date) AS day
, sum((select time_to_sec(timediff(end_date, start_date )) / 3600)) AS hours
FROM `timesheet_table`
WHERE id > 0
GROUP BY WEEKDAY(start_date), user_id
E.g.:
SELECT user_id
, DATE(start_date) dt
, SEC_TO_TIME(SUM(TIME_TO_SEC(end_date)-TIME_TO_SEC(start_date))) day_total
-- [or , SUM(TIME_TO_SEC(end_date)-TIME_TO_SEC(start_date))/3600 day_total]
FROM my_table
WHERE start_date BETWEEN '2016-10-01 00:00:00' AND '2016-10-07 23:59:59'
GROUP
BY user_id
, DATE(start_date);
The rest of the problem (missing days, display issues, weekly totals, etc.) would normally be handled in application level code.

Query that displays rows in a range of date with day, month and year

I have the following columns in my table Log:
year, month, day, info
I need a query that selects the rows in a range of date determined by the user. The user will select the initial day, month and year and also the final day, month and year. At the moment, my query is:
SELECT
CONCAT(LPAD(`day`,2, 0),'/',LPAD(`month`,2, 0),'/',`year`) AS data,
info
FROM
Log
WHERE
(year > :initial_year OR (year = :initial_year AND month >= :initial_moth AND day >= :initial_day))
AND (year < :final_year OR (year = :final_year AND month <= :final_month AND day <= :final_day))
GROUP BY
year, month, day
ORDER BY
year DESC, month DESC, day DESC
But this query doesn't display any results, even that they are in the database! What is wrong and how can I fix it?
Your logic is wrong:
WHERE (
year > :initial_year OR (
year = :initial_year AND month >= :initial_moth AND day >= :initial_day
)
)
Will exclude any dates in your initial year where the day portion is greater than the initial day portion. e.g. yyyy-01-31 as the initial day will exclude all results for yyyy where the day portion is not 31.
Similar problems exist with the final date.
As suggested in the comments, use one DATE field in your database and do the other fiddling in your application code; it will save a lot of drama.
If you can't change the database, find and berate the person who designed it until they change it. If you can't do that then:
WHERE (year>:initial_year OR (year=:initial_year AND (month>:initial_month OR (month=:initial_month AND day>=:initial_day))))
and similar for the final date
What about:
select
concat(year,month,day) as thedate, info
from
log
where
thedate >= :startdate and thedate <= :enddate
order by
thedate desc;

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.

sql query date filtering the result

i've create a database to store statistics from a website such as traffic. i'm trying to query the database for the number of unique ip addresses that have been captured over the last 30 days;
SELECT COUNT(*) totalA FROM statistics GROUP by ipAddress
AND DATE_SUB(CURDATE( ) ,INTERVAL 30 DAY) LIMIT 0, 30
however the query just return the number of data entry in the table. i've used the same query minus the date filter and gotten the correct result so it's just the date filtering thats messed up
any help would be appreciated thanks
It's because you're GROUP BY on the ipAddress AND DATE_SUB(CURDATE( ), INTERVAL 30 DAY) and this expression yields the logical AND between two fields, which has only 2 possible values. Still, you don't care bout the distinction and request just count(*).
What you probably want is:
SELECT ipAddress, DATE_SUB(CURDATE( ), INTERVAL 30 DAY), COUNT(*) AS totalA
FROM statistics
GROUP by ipAddress, DATE_SUB(CURDATE( ), INTERVAL 30 DAY)
LIMIT 0, 30
I think this is what you are looking for. Basically I just put your date code in a WHERE clause and compared it to the date column in your table. Obviously you will need to change the "entryDate" to whatever the name of your date column is.
SELECT COUNT(*) AS totalA
FROM statistics
WHERE entryDate >= DATE(CURDATE()-INTERVAL 30 DAY)
GROUP BY ipAdress

SQL Count Totals Within Date Ranges

I have a CHANGES table with fields VALUE(integer) and CREATED_AT(timestamp). I want to know the total of the VALUE column grouped by each of the past 30 days (without making 30 queries).
So if yesterday there were records created with VALUEs of 10, -7, and 12; I would want a record returned with CREATED_AT = yesterday and TOTAL = 15.
Any help?
SELECT date(created_at) as CREATED_AT, sum(value) as TOTAL
FROM changes
WHERE created_at >= curdate() - interval 30 day
GROUP BY date(created_at);
Well, it slightly depends on what kind the timestamp is formatted in (SQL/ Unix/ etc). But this type of query might help you along:
SELECT
DATE_FORMAT(CREATED_AT, '%Y-%m-%d') ym,
COUNT(VALUE)
FROM foo
GROUP BY ym