Mysql query extracting date + group by day - mysql

Simple question: Why does the following query not output perday?
SELECT FROM_UNIXTIME(`date`,"%Y-%m-%d") AS `perday`, COUNT(*) AS `count`
FROM `data`
WHERE `group` = 1
GROUP BY `perday`
Count gets outputted correctly, but perday stays empty.
The data table is like:
| id | group | date |
------------------------------------------------
| 1 | 1 | 2013-04-13 06:01:02 |
| 2 | 1 | 2013-04-13 14:24:18 |
| 3 | 2 | 2012-01-21 21:33:03 |
Ect.
Thanks!
EDIT:
Expected output:
| perday |
--------------
| 2013-04-13 |
| 2012-01-21 |

remove WHERE clause,
SELECT FROM_UNIXTIME(date,'%Y-%m-%d') AS perday,
SUM(`group` = 1) AS `count`
FROM data
GROUP BY FROM_UNIXTIME(date,'%Y-%m-%d')
if date is formatted as 2013-04-13 06:01:02, then why use FROM_UNIXTIME? Isn't it DATE_FORMAT instead?
SELECT DATE_FORMAT(date, '%Y-%m-%d') AS perday,
SUM(`group` = 1) AS `count`
FROM data
GROUP BY DATE(date)
ORDER BY date
This will display all available dates in the table.
SQLFiddle Demo
But if you want the selected group only,
SELECT DATE_FORMAT(date, '%Y-%m-%d') AS perday,
COUNT(*) AS `count`
FROM data
WHERE `group` = 1
GROUP BY DATE(date)
ORDER BY date

you may looking for this
SELECT DATE_FORMAT(`date`,"%Y-%m-%d") AS `perday`, COUNT(*) AS `count`
FROM `data`
WHERE `group` = 1
GROUP BY `perday`
DEMO HERE

MySQL DATE() takes the DATE part out from a DATETIME expression.As your Expected output this query is fine.
SELECT
DATE(`date`) AS `perday`,
COUNT(*) AS `count`
FROM `data`
GROUP BY `perday`

Related

Group together rows with similar date in SQL

In MySQL, I have a query that simplifies a table. Here is the query and the result:
Query:
SELECT
test.`ASSEMBLING-TAG`.`Name 5` AS tag,
DATE(test.`ASSEMBLING-TAG`.datetimetemp) AS date
FROM
test.`ASSEMBLING-TAG`
GROUP BY `Name 5` , datetimetemp
ORDER BY `Name 5`
Result:
From this result, I would like to group the rows by tags with the same date and count them, like so:
Expected output:
| tag | date | count |
|----------------|------------|-------|
| G_GoodPieces_R | 2016-01-01 | 10 |
| G_GoodPieces_R | 2016-01-02 | 1 |
How can I achieve that ?
Then simply group by the date of the datetime.
And count them.
SELECT
t.`Name 5` AS tag,
DATE(t.datetimetemp) AS date,
COUNT(*) AS Total
FROM test.`ASSEMBLING-TAG` t
GROUP BY t.`Name 5`, DATE(t.datetimetemp)
ORDER BY t.`Name 5`

Select last inserted value of each month for every year from DATETIME

I got a DATETIME to store when the values where introduced, like this example shows:
CREATE TABLE IF NOT EXISTS salary (
change_id INT(11) NOT NULL AUTO_INCREMENT,
emp_salary FLOAT(8,2),
change_date DATETIME,
PRIMARY KEY (change_id)
);
I gonna fill the example like this:
+-----------+------------+---------------------+
| change_id | emp_salary | change_date |
+-----------+------------+---------------------+
| 1 | 200.00 | 2018-06-18 13:17:17 |
| 2 | 700.00 | 2018-06-25 15:20:30 |
| 3 | 300.00 | 2018-07-02 12:17:17 |
+-----------+------------+---------------------+
I want to get the last inserted value of each month for every year.
So for the example I made, this should be the output of the Select:
+-----------+------------+---------------------+
| change_id | emp_salary | change_date |
+-----------+------------+---------------------+
| 2 | 700.00 | 2018-06-25 15:20:30 |
| 3 | 300.00 | 2018-07-02 12:17:17 |
+-----------+------------+---------------------+
1 won't appear because is an outdated version of 2
You could use a self join to pick group wise maximum row, In inner query select max of change_date by grouping your data month and year wise
select t.*
from your_table t
join (
select max(change_date) max_change_date
from your_table
group by date_format(change_date, '%Y-%m')
) t1
on t.change_date = t1.max_change_date
Demo
If you could use Mysql 8 which has support for window functions you could use common table expression and rank() function to pick row with highest change_date for each year and month
with cte as(
select *,
rank() over (partition by date_format(change_date, '%Y-%m') order by change_date desc ) rnk
from your_table
)
select * from cte where rnk = 1;
Demo
The below query should work for you.
It uses group by on month and year to find max record for each month and year.
SELECT s1.*
FROM salary s1
INNER JOIN (
SELECT MAX(change_date) maxDate
FROM salary
GROUP BY MONTH(change_date), YEAR(change_date)
) s2 ON s2.maxDate = s1.change_date;
Fiddle link : http://sqlfiddle.com/#!9/1bc20b/15

MySQL sum a column based on another distinct column count

I need to get sum of hits based on distinct ip
So far, this is what I've come up with:
SELECT
COUNT(DISTINCT `ip`) AS `total`,
SUM(`hits`) AS `sum`
FROM `stats`.`stats`
WHERE `category`=?
GROUP BY `date`
Sample data:
| category | ip | hits | date |
| 11 | ip1 | 1000 | date1 |
| 11 | ip2 | 1000 | date1 |
| 11 | ip3 | 1000 | date1 |
| 11 | ip4 | 1000 | date1 |
| 11 | ip1 | 1000 | date1 |
Expected results:
ip=4
sum=4000
I am getting as
ip=4
sum=5000
But this is giving total ip hits instead if summing only distinct ip hits.
Please suggest a way to do this. I would prefer doing something like
SUM(CASE WHEN `ip` THAN `hits`)
//or
SUM(CASE WHEN IN(`ip`) THAN `hits`)
//or
SUM(CASE WHEN IF(`ip`) THAN `hits`)
instead of subquery as I need fast query.
Also using array_unique PHP side will be good for me.
You can do it like this:
SELECT count(s.ip) as cntIp,sum(s.hits) as sumHits
FROM(
SELECT DISTINCT t.ip,t.hits
FROM YourTable t) s
But it looks like the data you provided is not accurate, I see that you group by date, which means that the date equals and not like in your example date1,date2,date3...
So:
SELECT s.date,count(s.ip) as cntIp,sum(s.hits) as sumHits
FROM(
SELECT DISTINCT t.ip,t.hits,t.date
FROM YourTable t) s
GROUP BY s.date
EDIT:
SELECT s.date,count(s.ip) as cntIp,sum(s.hits) as sumHits
FROM(
SELECT t.ip,t.hits,t.date
FROM YourTable t
GROUP BY t.ip,t.hits,t.date) s
GROUP BY s.date
You need to write a subquery that returns the minimum hit value for each ip/date. Then you can sum these.
SELECT date, count(*) as sum, sum(minhits) as hits
FROM(
SELECT ip, date, MIN(hits) AS minhits
FROM stats
WHERE category = ?
GROUP BY ip, date) AS subquery
GROUP BY date
You can try this
SELECT
`ip`
COUNT(`ip`) AS `total`,
SUM(`hits`) AS `sum`
FROM
`stats`.`stats`
WHERE
`category`=?
GROUP BY
`date`,
`ip`

MySQL View to do a Group by after an Order by

the "t_example" table :
id | date
---------------
1 | 2001-05-09
1 | 2005-11-05
1 | 2000-08-19
2 | 2010-10-30
2 | 2002-12-10
2 | 2009-07-29
3 | 2003-02-15
3 | 2012-04-20
I would like to create a view that returns the following result (the max date for each id):
id | date_id
---------------
1 | 2005-11-05
2 | 2010-10-30
3 | 2012-04-20
MySQL don't allow to do a subquery with order by in view, and when I use an other view for the subquery, the group by ignore the order by in the subquery.
The following query returns the expected result:
select id, date
from (select id, date from t_example order by id asc, date_id desc) p
group by p.id
But when I use it in a views it does't work:
view1 (subquery) : select id, date from t_example order by id asc, date_id desc;
view2 : select id, date from view1 group by view1.id;
Is there any other solution?
This should work for you
SELECT id, MAX(date) AS date FROM t_example GROUP BY id;
This is using the AS syntax to keep your column name succinct (otherwise it would be MAX(date))
select id,max(date)
from your_table
group by id

Sort data before using GROUP BY?

I have read that grouping happens before ordering, is there any way that I can order first before grouping without having to wrap my whole query around another query just to do this?
Let's say I have this data:
id | user_id | date_recorded
1 | 1 | 2011-11-07
2 | 1 | 2011-11-05
3 | 1 | 2011-11-06
4 | 2 | 2011-11-03
5 | 2 | 2011-11-06
Normally, I'd have to do this query in order to get what I want:
SELECT
*
FROM (
SELECT * FROM table ORDER BY date_recorded DESC
) t1
GROUP BY t1.user_id
But I'm wondering if there's a better solution.
Your question is somewhat unclear but I have a suspicion what you really want is not any GROUP aggregates at all, but rather ordering by date first, then user ID:
SELECT
id,
user_id,
date_recorded
FROM tbl
ORDER BY date_recorded DESC, user_id ASC
Here would be the result. Note reordering by date_recorded from your original example
id | user_id | date_recorded
1 | 1 | 2011-11-07
3 | 1 | 2011-11-06
2 | 1 | 2011-11-05
5 | 2 | 2011-11-06
4 | 2 | 2011-11-03
Update
To retrieve the full latest record per user_id, a JOIN is needed. The subquery (mx) locates the latest date_recorded per user_id, and that result is joined to the full table to retrieve the remaining columns.
SELECT
mx.user_id,
mx.maxdate,
t.id
FROM (
SELECT
user_id,
MAX(date_recorded) AS maxdate
FROM tbl
GROUP BY user_id
) mx JOIN tbl t ON mx.user_id = t.user_id AND mx.date_recorded = t.date_recorded
Iam just using the technique
"Using order clause before group by inserting it in group_concat clause"
SELECT SUBSTRING_INDEX(group_concat(cast(id as char)
ORDER BY date_recorded desc),',',1),
user_id,
SUBSTRING_INDEX(group_concat(cast(`date_recorded` as char)
ORDER BY `date_recorded` desc),',',1)
FROM data
GROUP BY user_id