How to get a daily SUM of numbers with MySQL? - mysql

I have a table, which looks like the following:
Table users:
id points date
1 100 2014-07-01
2 500 2014-07-02
3 200 2014-07-01
4 100 2014-07-03
5 100 2014-07-01
6 400 2014-07-02
7 800 2014-07-02
8 200 2014-07-02
Now, how is it possible to select each unique date and count the sum of the points on those days?
So I's need a result something like this:
points date
400 2014-07-01
1900 2014-07-02
100 2014-07-03

SELECT SUM(`points`) AS points, `date`
FROM users
GROUP BY `date`

Try this:
SELECT SUM(points) points, date
FROM users
GROUP BY date
ORDER BY date ASC

This group-and-aggregate operation is a standard query pattern and can be solved following these steps1.
Use a GROUP BY date to aggregate the dates into groups, by date.
Select SUM(points) to tally the points in each aggregated [date] group.
Select the date column, which represents each group, to include it in the results.
Finally, apply ORDER BY date to ensure the results are ordered.
1 It is good etiquette - and results in better answers/discussion - when discussing attempted solutions (ie queries) in questions, and why they didn't work [correctly].

Related

How to average a value in a time window for multiple days, in Mysql?

Having this simple log table
id |val |dt
-------------------------
A 100 2014-01-15 00:00:00
A 160 2014-01-15 00:00:00
A 100 2014-01-15 01:00:00
A 160 2014-01-15 02:00:00
A 200 2014-01-15 03:00:00
A 80 2014-01-16 01:00:00
B 100 2014-01-16 02:00:00
B 200 2014-01-16 01:00:00
B 100 2014-01-15 02:00:00
and so on...
I can average a SINGLE day(15), of a SINGLE given id (A), in a specified range (0-2) by doing this
select id,
date(dt),
AVG(val) as av
from (SELECT id, val, dt
FROM test
WHERE id = 'A' AND
(date(dt) BETWEEN '2014-01-15' AND '2014-01-15') AND
( (time(dt) BETWEEN '00:00' AND '02:00'))) as outerTable
I get this SINGLE result
id |date | average 00:00 to 2:00
-------------------------
A 2014-01-15 120.0000
But how to solve that average of MULTIPLE days in same time period, but in many days in range of months? years? like
id |date | average 00:00 to 2:00
-------------------------
A 2014-01-15 120.0000
A 2014-01-16 80.0000
A 2014-01-17 35.0000
and so on...
Need of loop the same query on different days for the whole month or year, of course the literal loop can be done in php, but it is SLOW, Also I could loop for every ID, making it slower.
You do not need to use Subquery, to get the data and then calculate the average in the Outer query. It can be done without the subquery itself.
In order to get the average value for different dates, you can remove the WHERE condition on date, to get the data for all the date(s). You can also change the WHERE condition on date to include a range instead.
You also seem to want results for different id values. We can get rid of WHERE condition on id as well.
Eventually, you can do a GROUP BY on the id and date, to get individual rows idwise, and then datewise.
SELECT
id,
DATE(dt)
AVG(val)
FROM test
WHERE
TIME(dt) BETWEEN '00:00' AND '02:00'
GROUP BY id, DATE(dt)

Run complicated query on multiple dates

I have the following query to get the monthly amount of users:
SELECT count(user_id) from subs
where (started_at between #start_date and #start_date + interval 1 month
or (expires_at>#start_date + interval 1 month and started_at<#start_date))
If we had the following DB:
user_id started_at expires_at
=============================
1 2015-01-01 2015-12-31
2 2015-01-01 2015-01-03
3 2015-02-01 2015-02-28
4 2015-03-01 2015-03-31
5 2015-04-01 2015-04-31
6 2015-04-01 2016-04-01
7 2015-05-01 2015-05-09
I need a query that will return the following table:
2015-01 - 2
2015-02 - 2 (because one of Jan records doesn't expire till Dec)
2015-03 - 2
2015-04 - 3
2015-05 - 3
etc
So what is the efficient way to get this result in one query?
You probably want something like this:
SELECT YEAR(started_at) as 'Year',
MONTH(started_at) as 'Month',
COUNT(user_id) as 'Users'
FROM subs
GROUP BY YEAR(started_at),MONTH(started_at);
Note that in case a month has no users, this query will not return an entry for that month. If you want to also include months with 0 users you want a more complex query; check this for more info.
You want to GROUP BY the year and month.
Assuming your started_at column is of a DATE type, you can f.e. use GROUP_BY YEAR(started_at), MONTH(started_at), or also use DATE_FORMAT to format the column value to a single string value, of the form YYYY-MM and GROUP BY that. Select that same value as a column too, to get the proper identifier you want.

mysql group by day and count then filter only the highest value for each day

I'm stuck on this query. I need to do a group by date, card_id and only show the highest hits. I have this data:
date card_name card_id hits
29/02/2016 Paul Stanley 1345 12
29/02/2016 Phil Anselmo 1347 16
25/02/2016 Dave Mustaine 1349 10
25/02/2016 Ozzy 1351 17
23/02/2016 Jhonny Cash 1353 13
23/02/2016 Elvis 1355 15
20/02/2016 James Hethfield 1357 9
20/02/2016 Max Cavalera 1359 12
My query at the moment
SELECT DATE(card.create_date) `day`, `name`,card_model_id, count(1) hits
FROM card
Join card_model ON card.card_model_id = card_model.id
WHERE DATE(card.create_date) >= DATE(DATE_SUB(NOW(), INTERVAL 1 MONTH)) AND card_model.preview = 0
GROUP BY `day`, card_model_id
;
I want to group by date, card_id and filter the higher hits result showing only one row per date. As if I run a max(hits) with group by but I won't work
Like:
date card_name card_id hits
29/02/2016 Phil Anselmo 1347 16
25/02/2016 Ozzy 1351 17
23/02/2016 Elvis 1355 15
20/02/2016 Max Cavalera 1359 12
Any light on that will be appreciated. Thanks for reading.
Here is one way to do this. Based on your sample data (not the query):
select s.*
from sample s
where s.hits = (select max(s2.hits)
from sample s2
where date(s2.date) = date(s.date)
);
Your attempted query seems to have no relationship to the sample data, so it is unclear how to incorporate those tables (the attempted query has different columns and two tables).

Replacement of correlated query

I have table with name orders:
id id_o value date
1 1 400 2014-09-30
2 1 300 2014-09-30
3 1 200 2014-09-30
4 2 100 2014-09-30
5 2 200 2014-09-30
6 3 50 2014-09-29
7 3 100 2014-09-29
8 4 300 2014-09-29
9 5 600 2014-09-28
I need select every order grouped by id_o with sum(value)< 700 and from this selected table i need display data grouped by datum.
I use multiple select:
select date, sum(mno) as mn
from (
select date,sum(value) as 'mno'
from orders
group by id_o
having sum(value)<700
) table_alias
group by date
This is result:
date mn
2014-09-30 300
2014-09-29 450
2014-09-28 600
Is there any possibility to replace or to simplify this correlated query?
Your inner query is invalid. It groups by id_o, but selects by date. In order to solve this, add an additional column to the inner queries grouping (assuming date is always the same for every id_o). You can enable strong checking by enabling the sql_mode's ONLY_FULL_GROUP_BY. Full example in SQL fiddle.
SELECT
date,
SUM(mno) AS mn
FROM (
SELECT
id_o,
date,
SUM(value) AS mno
FROM orders
GROUP BY
id_o,
date
HAVING
SUM(value) < 700
) totalPerOrder
GROUP BY date
MySQL allows this type of queries, but it's not common to do so. Consider the following data:
id id_o value date
1 1 400 2014-09-29
2 1 300 2014-09-30
3 1 200 2014-09-30
What date(s) would SELECT date, SUM(value) FROM orders GROUP BY id_o return? It could be the first, last, average, most common one, but better make it explicit. Any other DBMS wouldn't let you execute this query.
Other than that, I would rename some of the columns to be more expressive. mn, mn_o and id_o are examples of this. Also value describes nothing, anything can be a value. Even the date field could have been called value. The query itself seems fine (take care if possibly missing indexes though).

How may i group this data in mysql

I Have a table called
CountryVisits
Visitor Date
4 20/12/12 14:27:7
5 20/12/12 15:45:11
6 20/12/12 16:36:51
12 21/12/12 11:17:2
145 21/12/12 12:37:57
445 21/12/12 13:35:15
435 21/12/12 14:34:35
I want to have a count of all visitors per Date not time :
So i expect :
VisitorCnt Date
3 20/12/12
4 21/12/12
I tried :
SELECT COUNT(DATE(Date)), DATE(Date) from CountryVisits GROUP BY Date ;
But i don't have the desired results.
When you write GROUP BY Date it's grouping by the Date column in the table, which includes times. If you want to group by just the day, you need to assign an alias and group by that:
SELECT COUNT(*), DATE(Date) AS VisitedOn
FROM CountryVisits
GROUP BY VisitedOn