Need to pull last x number of rows based on date - mysql

I have a table with dates in "Aug 23, 2009" format and 5 values, so that it looks like this
SELECT * FROM table;
Date | Total | V1 | V2 | V3 | V4
Aug 21, 2009 | 41 | 23 | 8 | 8 | 2
Aug 22, 2009 | 39 | 22 | 8 | 7 | 2
Aug 23, 2009 | 35 | 20 | 6 | 7 | 2
Aug 24, 2009 | 34 | 20 | 6 | 6 | 2
Aug 25, 2009 | 32 | 19 | 5 | 6 | 2
Aug 26, 2009 | 31 | 19 | 5 | 5 | 2
Aug 27, 2009 | 30 | 19 | 5 | 5 | 1
So I need a query that will give me only the most recent (bottom) 3 entries. Should I setup some query by the date or just set a limit to the last 3 rows? I tried doing a subquery with a limit, but my version of MySQL does not support LIMIT in subquery, and to my knowledge there is no way to do a negative limit to grab the last x number of rows.

select *
from table
order by Date desc
limit 0, 3

Can MySQl do TOP ? If so
Select Top 3 * From Table
Order By Date Desc

Just change the order by to do your LIMIT.
So, in other words, add
ORDER BY `date` DESC
to your select statement. You'll then be a ble to limit the return results to whatever row count you need.

You don't need a sub-query, just use a LIMIT clause in your SELECT statement, and add an ORDER BY 'date' DESC clause. Generally it is a bad idea to use column names such as 'DATE' (or 'DATETIME' for that matter) because different databases may use these as reserved words.

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 - Select query generating a column for each month in date range

I have a request for a report that must return the total qty of items shipped, grouped by item, within a date range. No big deal. BUT they want the report to display one column for each month in the range.
Example: Customer specified start date = 2017-11-15 and end date = 2018-03-14
There is a bunch of columns prior to the month columns, but for the sake of simplicity, I'll use only ITEMCODE in the example. The result should look like the following:
ITEMCODE | NOV 17 | DEC 17 | JAN 18 | FEB 18 | MAR 18
SHIRT123 | 10 | 25 | 33 | 20 | 7
PANTS123 | 5 | 20 | 20 | 18 | 6
I don't even know if it's possible to do this. Note, under each month is the sum of the QTY column.

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)

An SQL Statement to sort within a query

I want to develop code that will allow a subset within a query. I have three fields "batchid", "month" and "year". Each batch may have several months and more than one year. The final order I need is the highest month year combination.
The following table I hope illustrates this.
Batch Month Year
5 12 2013
1 2014
6 11 2013
3 2014
4 1 2014
2 2014
The required order is
Batch Month Year
5 12 2013
1 2014
4 1 2014
2 2014
6 11 2013
3 2014
You can see each batch is sorted to the latest date in the batch and each batch is ordered to the latest date in the batch.
I have got it as far as the year is concerned but cannot figure out the month.
The first statement determines the lowest and highest dates.
I am new to this forum and for that matter not experienced using VBA and have not beanpole to get the SQL statement into this post so I apologize na hope this may make sense.
SELECT t1.batch, t1.month, t1.year
FROM tmp t1
JOIN
(SELECT batch, max(year*12+month) mord FROM tmp GROUP BY batch ORDER BY mord) t2
ON t2.batch = t1.batch
ORDER BY t2.mord, t1.year, t1.month
yields
+-------+-------+------+
| batch | month | year |
+-------+-------+------+
| 5 | 12 | 2013 |
| 5 | 1 | 2014 |
| 4 | 1 | 2014 |
| 4 | 2 | 2014 |
| 6 | 11 | 2013 |
| 6 | 3 | 2014 |
+-------+-------+------+

Query to select intervals in day

I have table something like this (there's also "device_id" and "timestamp" columns)
day | interval | value
----------------------------
1 | 14 | 63 // start of a day
1 | 14 | 83
1 | 14 | 73
1 | 15 | 23
1 | 15 | 33
1 | 15 | 50
2 | 16 | 23 // start of a day
2 | 16 | 33
2 | 16 | 50
I want to select all intervals in a day. That is simple.
However, an interval can start a bit before a day flips, or end a bit past:
day | interval | value
----------------------------
7 | 14 | 63
7 | 14 | 83
8 | 14 | 73 // start of a day
8 | 15 | 23
8 | 15 | 33
8 | 15 | 50
8 | 16 | 23
8 | 16 | 33
9 | 16 | 50 // start of a day
Now I'd like to select all three intervals - or even better intervals that are mostly in that day.
SELECT ... WHERE day = 8
Gives me only parts of the start/end intervals (14, 16). That's useless, I need the complete intervals.
If there's no solution, I'll just do three queries, but there might be some SQL trick I'm not aware of?
It's MySQL, called from PHP.
More visually:
day 7 | day 8 | day 9
------------------+-------------------+---------------
###13### ###14### ###15### ###16### ###17###
... 63 83 73 23 33 50 23 33 50 ...
I want all values in day 8 -> intervals 14, 15, 16
I think you are looking for this:
SELECT * FROM intervals
WHERE interval IN (
SELECT DISTINCT interval FROM intervals WHERE day = 8)
This selects all interval data where at least one of the entries for that interval occurs in day 8. The subquery determines which unique intervals happen in the day, which is then used by the outer query to select their specifics.
SELECT DISTINCT y.*
FROM my_table x
JOIN my_table y
ON y.some_column = x.some_column
WHERE x.some_other_column = 8;