MYSQL - Grouping & Max? - mysql

I have a table that produces the following results:
userid statusid no name area month year dateupdated
62 2 763 ABCD Brazil 6 2013 2013-11-26 15:28
62 1 869 ABC Brazil 7 2012 2013-11-26 15:10
62 2 869 ABC Brazil 6 2013 2013-11-26 15:28
62 1 869 ABC Brazil 6 2013 2013-11-26 14:50
61 1 763 ABCD Brazil 6 2013 2013-11-26 14:50
54 1 200 ABCDE US 12 2013 2013-11-26 21:02
32 2 200 ABCDE US 12 2013 2013-11-26 21:03
I want to be able to show the latest 'no' per row. I have tried using max(dateupdated), but still shows all the records. I've also tried grouping, but also no luck.
I only need to see the latest record determined by the dateupdated.
Can anyone please assist me?

I'm not sure I understand your question, but you might be helped by something like this:
select * from mytable where dateupdated = (select max(dateupdated) from mytable);
EDIT:
Based on your clarification, you need in that case a correlated subquery. I haven't tried this, but perhaps something like:
select *
from mytable a
where dateupdated = (select max(dateupdated) from mytable where no = a.no);

Or this:
SELECT *
FROM table
ORDER BY dateupdated DESC
LIMIT 1;
Last for every no: (Is this what you want ?)
SELECT *
FROM table t1
WHERE NOT EXISTS(SELECT * FROM table t2
WHERE t1.no = t2.no
AND t2.dateupdated > t1.dateupdated)

Query:
SQLFIDDLEExample
SELECT t1.*
FROM Table1 t1
LEFT JOIN Table1 t2 ON t2.dateupdated > t1.dateupdated
AND t1.no = t2.no
WHERE t2.no IS NULL
Result:
| USERID | STATUSID | NO | NAME | AREA | MONTH | YEAR | DATEUPDATED |
|--------|----------|-----|-------|--------|-------|------|---------------------------------|
| 62 | 2 | 763 | ABCD | Brazil | 6 | 2013 | November, 26 2013 15:28:00+0000 |
| 62 | 2 | 869 | ABC | Brazil | 6 | 2013 | November, 26 2013 15:28:00+0000 |
| 32 | 2 | 200 | ABCDE | US | 12 | 2013 | November, 26 2013 21:03:00+0000 |

Tag along a LIMIT 1; at the end of your query and sort descending.

Related

How to write an SQL query to calculate the average for three consecutive values?

I have a table like this
userID time NoOfVisits
1 2014 50
2 2015 60
3 2016 70
4 2017 80
5 2018 90
6 2019 100
I need to write a sql query which will print time and average of past 3 years NoOfVisits for a particular site.
output should be as
userID time NoOfVisits
1 2014 50.0000
2 2015 55.0000
3 2016 60.0000
4 2017 70.0000
5 2018 80.0000
6 2019 90.0000
Explanation :
For user Id 6 (80+90+100)/3=90.0000
Please help me to solve this problem.
You can use a cumulative average, available in MySQL 8+:
select t.*,
avg(visits) over (order by time rows between 2 preceding and current row) as avg_visits_3
from t;
Assuming there are no gaps between the years (like your sample data), you can self join the table and group by userid, time to get the average:
select
t.userid, t.time, avg(tt.noofvisits) NoOfVisits
from tablename t inner join tablename tt
on tt.time between t.time - 2 and t.time
group by t.userid, t.time
See the demo.
Results:
| userid | time | NoOfVisits |
| ------ | ---- | ---------- |
| 1 | 2014 | 50 |
| 2 | 2015 | 55 |
| 3 | 2016 | 60 |
| 4 | 2017 | 70 |
| 5 | 2018 | 80 |
| 6 | 2019 | 90 |

MySQL `SUM` with `GROUP BY` is missing data in results

I have a database with a table containing information on some images, each row containing a createdAt date and a viewCount. The data ranges from September 2014 until today (July 2016). I want to get a monthly sum of the amount of views across all images for the month
When I run the query
SELECT YEAR(createdAt), MONTH(createdAt), SUM(viewCount)
FROM Images
GROUP BY MONTH(createdAt);
I'm only returned 12 rows with results between September 2014 and August 2015
Year | Month | Views
-------------------
2014 | 9 | 1452
2014 | 10 | 279
2014 | 11 | 34428
2014 | 12 | 4763
2015 | 1 | 2826
2015 | 2 | 777
2015 | 3 | 568
2015 | 4 | 1309
2015 | 5 | 46744
2015 | 6 | 1541
2015 | 7 | 8160
2015 | 8 | 91
If I add a date restraint it will give me the latest data, but again only 12 rows
SELECT YEAR(createdAt), MONTH(createdAt), SUM(viewCount)
FROM Images WHERE createdAt > DATE('2015-08-01 00:00:00')
GROUP BY MONTH(createdAt);
Year | Month | Views
--------------------
2015 | 8 | 981
2015 | 9 | 1031
2015 | 10 | 2566
2015 | 11 | 3325
2015 | 12 | 411
2016 | 1 | 2140
2016 | 2 | 710
2016 | 3 | 714
2016 | 4 | 1985
2016 | 5 | 426
2016 | 6 | 119
2016 | 7 | 81
I do realise that since it's July the second query stops there as that's where the data ends, but why does the first query not return all the results?
Group by year/month:
SELECT YEAR(createdAt), MONTH(createdAt), SUM(viewCount)
FROM Images
--WHERE createdAt > DATE('2015-08-01 00:00:00')
GROUP BY YEAR(createdAt), MONTH(createdAt);
Related Group by clause in mySQL and postgreSQL, why the error in postgreSQL?
Keep in mind that from MySQL 5.7.6+ your initial query may not even work because of only_full_group_by which is set by default.
You can simply add Year to you group by
SELECT YEAR(createdAt), MONTH(createdAt), SUM(viewCount)
FROM Images
GROUP BY YEAR(createdAt), MONTH(createdAt)
ORDER BY YEAR(createdAt), MONTH(createdAt)

how to to get a record from mysql 20 consecutive days?

I have a table XX. i need to get the records which are 20 days consecutive gap .below is my table look
ID ISmen Date
1 0 2013-05-2
2 0 2013-05-2
3 0 2014-04-2
4 1 2014-05-2
5 1 2014-05-2
6 0 2014-05-2
7 0 2014-05-2
8 0 2014-05-2
9 1 2014-05-25
10 1 2014-05-25
11 0 2014-05-26
12 1 2014-05-27
13 0 2014-05-28
From the above table i need to get the records which are ismen is 1 and the next record ismen is also 1 (i.e 4,5 and 9,10 but not 12).and one more thing 4,5 and 9,10 should have 20 days gap
i am getting the records which are 4,5 and 9,10 ..but i can't able to check date difference between the records .i know we can achieve in the loop but i am trying to get in MySQL is it possible or not.I try below query.thanks in advance for help
SELECT *
FROM XX t1,
XX t2
WHERE (t1.ID=t2.ID+1
OR t1.ID=t2.ID-1)
AND t1.Ismen=1
AND t2.Ismen=1
There is a 23 day gap between |4|5| to |9|10| but ignoring the sample data precision, this result:
| ISMEN | T1ID | T2ID | T1DATE | T2DATE |
|-------|------|------|----------------------------|----------------------------|
| 1 | 4 | 9 | May, 02 2014 00:00:00+0000 | May, 25 2014 00:00:00+0000 |
| 1 | 5 | 9 | May, 02 2014 00:00:00+0000 | May, 25 2014 00:00:00+0000 |
| 1 | 4 | 10 | May, 02 2014 00:00:00+0000 | May, 25 2014 00:00:00+0000 |
| 1 | 5 | 10 | May, 02 2014 00:00:00+0000 | May, 25 2014 00:00:00+0000 |
was produced by this query:
select
t1.ismen
, t1.id as t1id
, t2.id as t2id
, t1.`date` as t1date
, t2.`date` as t2date
from table1 as t1
inner join table1 as t2 on t1.ismen = t2.ismen
and t1.`date` + INTERVAL 23 DAY = t2.`date`
The wanted gap between records can be defined in the join conditions (change to 20 or whatever). But do note there is nothing to stop 4 relating to 9 and 10 or 5 to 9 & 10 so you get 4 records in total.
see: http://sqlfiddle.com/#!9/8d941/1
You could reduce that result by some means (e.g. using row_number() but I don't know if that is required.

How to get difference of two rows in same column

I have to find the difference in the value of a single column of table as current row value-previous row value for some 'n' number of rows in one column and also I don't have ID to use as reference for increment
date: box_count : total_no_of_boxes_used
1/12/12 2 2
2/12/12 8 6
3/12/12 14 6
I have box_count column and I am trying to get total_no_of_boxes_used column.
Please help me.
Thanks in advance
Given your records are sequential by date.....
SQLFIDDLE DEMO
Query:
select a.date, a.bc, case when (a.bc-b.bc) is null then a.bc else a.bc-b.bc end tot
from tt a
left join
tt b
on a.date > b.date
group by b.date
;
Results:
DATE BC TOT
December, 01 2012 00:00:00+0000 2 2
December, 02 2012 00:00:00+0000 8 6
December, 03 2012 00:00:00+0000 14 6
December, 04 2012 00:00:00+0000 23 9
One way to do this, is using a correlated subquery like so:
SELECT
t1.`date`,
t1.box_count,
t1.box_count -
IFNULL((SELECT t2.box_count
FROM table1 t2
WHERE t2.`date` < t1.`date`
ORDER BY t2.`date` DESC
LIMIT 1),
0 ) AS total_no_of_boxes_used
FROM table1 t1;
SQL Fiddle Demo
This will give you:
| DATE | BOX_COUNT | TOTAL_NO_OF_BOXES_USED |
------------------------------------------------------------------------
| January, 12 2012 00:00:00+0000 | 2 | 2 |
| February, 12 2012 00:00:00+0000 | 8 | 6 |
| March, 12 2012 00:00:00+0000 | 14 | 6 |
Try this:
SELECT date,
(box_count - #diff) total_no_of_boxes_used,
(#diff:=box_count) box_count
FROM table1, (SELECT #diff:=0) A;
Check this SQL FIDDLE DEMO
OUTPUT
| DATE | TOTAL_NO_OF_BOXES_USED | BOX_COUNT |
------------------------------------------------------------------------
| January, 12 2012 00:00:00+0000 | 2 | 2 |
| February, 12 2012 00:00:00+0000 | 6 | 8 |
| March, 12 2012 00:00:00+0000 | 6 | 14 |

MySql subquerying to pull data from another table

I am currently using phpMyAdmin supporting MySql 5.0.
I have the following two tables:
Master Facebook Insights
------------------------
Client ID Client Name Date Top Likes By Gender
--------- ----------- ------ --------------------
1 Client1 2012-01-01
1 Client1 2012-02-01
2 Client2 2012-01-01
2 Client2 2012-02-01
...etc. (the dates are always the beginning of each month for however many months
& clients exist)
Likes By Demographic
----------------
Date Demographic1 Demographic2 Demographic3 Client
------ ------------ ------------ ------------ ------
0000-00-00 M.35-44 M.45-54 M.25-34 1
2012-01-01 53 44 28 1
2012-01-02 53 46 29 1
...etc.
0000-00-00 M.18-24 M.35-44 M.25-34 1
2012-02-01 374 221 194 1
2012-02-02 374 222 195 1
...etc.
0000-00-00 F.35-44 F.25-34 M.35-44 2
2012-01-01 194 182 83 2
2012-01-02 194 182 83 2
...etc.
0000-00-00 F.35-44 F.25-34 M.35-44 2
2012-02-01 196 180 83 2
2012-02-02 197 180 83 2
...etc.
For the Likes By Demographic table:
All days of each month are listed per client; when a new month begins,
there is a new set of demographics that may or may NOT be listed exactly the same
as the previous month. This is because the data was imported from a CSV that put the demographics in order of highest 'likes,' so this usually changes month to month. This is also the reason that the individual demographics are not the column headers (because they are inconsistent).
My problem is the following:
I wish to list the top 3 demographics per month for each client in the 'Top Likes By Gender' column of the first table, like so:
Client ID Client Name Date Top Likes By Gender
--------- ----------- ------ --------------------
1 Client1 2012-01-01 M.35-44, M.45-54, M.25-34
1 Client1 2012-02-01 M.18-24, M.35-44, M.25-34
2 Client2 2012-01-01 F.35-44, F.25-34, M.35-44
2 Client2 2012-02-01 F.35-44, F.25-34, M.35-44
The use of subqueries is confusing me. The following is the (incorrect) code I have been trying to fix. The problem is that is just extracts the first three demographics for the first client (M.35-44, M.45-54, M.25-34) and repeats them down the entire column for all clients and dates.
Am I on the right track, or is there a much simpler/more correct way to do this?
UPDATE `Master Facebook Insights`
SET `Top Likes By Gender` =
(select * from
(SELECT DISTINCT CONCAT(`Demographic1`,', ',`Demographic2`,', ',`Demographic3`)
FROM `Likes By Demographic` t1
JOIN `Master Facebook Insights` t2
ON t1.`Client` = t2.`Client ID`
WHERE t1.`Date` = '0000-00-00'
AND t2.`Date` =
(
SELECT MIN(`Date`)
FROM `Likes By Demographic`
WHERE `Date` > '0000-00-00'
AND `Client` = t2.`Client ID`
GROUP BY `Date`
ORDER BY `Date` ASC
LIMIT 1
)
)inner1 limit 1)
Thank you so much for the help!
Just using the original Likes_By_Demographic table, you can do:
select
client_id,
date,
concat(demo1,', ',demo2,', ',demo3) `top_likes`
from likes_by_demographic
group by client_id, date
order by client_id, date;
...which will yield (pseudo-data):
| CLIENT_ID | DATE | TOP_LIKES |
-----------------------------------------------------------------------
| 1 | January, 01 2012 00:00:00-0800 | M.35-44, M.25-34, 195 |
| 1 | February, 01 2012 00:00:00-0800 | M.25-34, M.35-44, 195 |
| 1 | March, 01 2012 00:00:00-0800 | M.25-34, 195, 169 |
| 2 | January, 01 2012 00:00:00-0800 | F.45-54, 210, 195 |
| 2 | February, 01 2012 00:00:00-0800 | F.45-54, 210, 75 |