SQL Count Totals Within Date Ranges - mysql

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

Related

How to select different values in different dates in SQL

Im trying to get the number of customers that a company had each day for the last 7 days. But when I run my code I get the total of customers for the week and is just displaying the last order date.
SELECT order_date, COUNT(DISTINCT buyerid) as 'customers' from orders
WHERE
date(order_date) >= curdate() - 7
AND date(order_date) <= curdate()
Your code is able to run because it's not in 'full group by only' mode. That is because you're not aggregating the order_date, so you end up displaying only the last date and counting all the buyerids. This is almost never an expected result, I might say.
I would rewrite it like so:
SELECT order_date, COUNT(DISTINCT buyerid) as 'customers'
FROM orders
WHERE
order_date >= date_sub(curdate(), interval 1 week)
GROUP BY order_date
Now it will count the distinct buyerids in each day.
Also, curdate() - 7 doesn't seem to work so I rewrote it entirely, assuming order_date is of date type.
Mind you might miss results if its a datetime, and in that case compare it to now() or strip time entirely.
I don't get the meaning of the line AND date(order_date) = curdate(). It seems to be right only if you want today's sales.

Count the number of events on a day of the month in MySQl

I want to count the number of events that occur on any given day of the month, ie 1st to 31st. not Month specific. So that I can see at what time of the month the most events are happening.
I can get the total the number of events on a specific dateTime that spans a couple of months with this query
SELECT COUNT(*), DATE(created_at)
FROM loan
WHERE DATE(created_at) >= DATE('2020-08-01')
AND DATE(created_at) <= DATE('2020-12-31')
GROUP BY DATE(created_at);
For example, 10 events happen on the 7th day of the month, 50 events happen on the 29th. So I can see that there is more activity at the end of the month.
Use DAY() instead of DATE():
SELECT DAY(created_at), COUNT(*)
FROM loan
WHERE created_at >= '2020-08-01' AND
created_at < '2021-01-01'
GROUP BY DAY(created_at);
Note that you don't need all the DATE() functions in the WHERE clause. That can slow down performance if indexes could be used for the WHERE conditions.
Consider aggregating by DAY() rather than DATE():
SELECT COUNT(*), DAY(created_at)
FROM loan
WHERE created_at >= '2020-08-01' AND created_at < '2021-01-01'
GROUP BY DAY(created_at);
Note that I changed the where clause so it no function is applied on the column being filtered; this is more efficient, especially if you have an index on created_at.

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

MYSQL select where date within this day

MY query looks like this:
SELECT COUNT(entryID)
FROM table
WHERE date >= DATE_SUB(CURDATE(), INTERVAL 1 DAY)
Will this count the rows whose date values are within the day (starting at 12:00; not within 24 hours)? If not, how do I do so?
The following should be enough to get records within the current day:
SELECT COUNT(entryID)
FROM table
WHERE date >= CURDATE()
As Michael notes in the comments, it looks at all records within the last two days in its current form.
The >= operator is only necessary if date is actually a datetime - if it's just a date type, = should suffice.
Here's the solution:
SELECT COUNT(entryID)
FROM table
WHERE DATE(date) >= CURDATE()
Since my date column is type DATETIME, I use DATE(date) to just get the date part, not the time part.
CURDATE() returns a date like '2012-03-30', not a timestamp like '2012-03-30 21:38:17'. The subtraction of one day also returns just a date, not a timestamp. If you want to think of a date as a timestamp think of it as the beginning of that day, meaning a time of '00:00:00'.
And this is the reason, why this
WHERE date >= DATE_SUB(CURDATE(), INTERVAL 1 DAY)
and this
WHERE date > CURDATE()
do the same.
I have another hint: SELECT COUNT(entryID) and SELECT COUNT(*) give the same result. SELECT COUNT(*) gives the database-machine more posibilities to optimize counting, so COUNT(*) is often (not always) faster than COUNT(field).