I want to be able to contrast "last weeks" data against "this weeks" data and get the percent change. (i.e. +1.2% or -.5%)
Here's an example of the MySQL table:
Date | Happy | Sad | Angry | Fearful
2016-04-01 | 2 | 1 | 3 | 0
2016-04-02 | 3 | 1 | 3 | 1
2016-04-03 | 0 | 4 | 1 | 2
2016-04-04 | 1 | 3 | 2 | 1
So pretending that there are at least 14 rows here how would I go about getting the average of the first 7 days, the average of the previous 7 days, and then creating the comparison that shows the percentage difference?
I can get the most recent 7 days averages with the code below, but when I try and repeat it and change the offset it fails:
SELECT AVG(happy), AVG(sad), AVG(angry), AVG(fearful)
FROM table_name
LIMIT 0, 7
Use subqueries to calculate the averages for each week, using date ranges, and join them.
SELECT curWeek.happy AS curHappy, curWeek.sad AS curSad, curWeek.angry AS curAngry, curWeek.fearful AS curFearful,
prevWeek.happy AS prevHappy, prevWeek.sad AS prevSad, prevWeek.angry AS prevAngry, prevWeek.fearful AS prevFearful,
100*(curWeek.happy - prevWeek.happy)/prevWeek.happy AS happyChange,
100*(curWeek.sad - prevWeek.sad)/prevWeek.sad AS sadChange,
100*(curWeek.angry - prevWeek.angry)/prevWeek.angry AS angryChange,
100*(curWeek.fearful - prevWeek.fearful)/prevWeek.fearful AS fearfulChange
FROM (SELECT AVG(happy) AS happy, AVG(sad) AS sd, AVG(angry) AS angry, AVG(fearful) AS fearful
FROM tablename
WHERE date > NOW() - INTERVAL 1 WEEK) AS curWeek
JOIN (SELECT AVG(happy) AS happy, AVG(sad) AS sd, AVG(angry) AS angry, AVG(fearful) AS fearful
FROM tablename
WHERE date BETWEEN NOW() - INTERVAL 2 WEEK AND NOW() - INTERVAL 1 WEEK) AS prevWeek
Related
I have some problem to get previous day of the record from the database. My table look like this :
id total trx_date
1 | 100 | 2019-05-13 04:03:03 |
2 | 200 | 2019-05-13 14:13:48 |
3 | 300 | 2019-05-12 10:23:37 |
4 | 100 | 2019-05-10 12:14:14 | <<<<<<<<<<<
5 | 200 | 2019-05-10 15:23:38 |
6 | 400 | 2019-05-10 19:33:56 |
I'm able to take the previous date if there's no gap between the date, but I'm failed to get the previous date if there's no record on the previous date.
My code :
$this->db->select("id, total, trx_date")
->from("trx_table")
->where('date(trx_date)', date('Y-m-d', strtotime('-1 day')) )
->order_by("id","DESC")
->get();
So I expect to get the previous day of the record, not the previous day of the current date. Can you guys help me to resolve this issue?
Thank you
Select dates earlier than today, but sort them descending and get only one. This will return the latest date earlier than today:
SELECT id, total, trx_date
FROM trx_table
WHERE trx_date < NOW()
ORDER BY trx_date DESC
LIMIT 1
Database table i have:
S.no | j_id |age | e_date |
-------------------------------------
1 | 1 |32 | 2018-05-09 |
-------------------------------------
-------------------------------------
1 | 1 |32 | 2018-05-09 |
-------------------------------------
-------------------------------------
1 | 2 |32 | 2018-05-09 |
-------------------------------------
-------------------------------------
1 | 2 |32 | 2018-04-16 |
-------------------------------------
-------------------------------------
1 | 1 |32 | 2018-09-16 |
-------------------------------------
-------------------------------------
1 | 3 |32 | 2018-04-16 |
------------------------------------
In my table I have expiry date I want to get the count of the result whose expiry date (90 days before) is equal to current date.
like I have expiry date 2018-05-09 and current date is 2018-02-2018 (90 days before date ) now i want to get to the count of the 90 days before result by query.
select * from yourtable
where datediff(CURDATE(), e_date) > 90
try to use datediff to get the different date count in day. Hope that this is what you want to get.
I like to keep the logic on the PHP side as much as possible, so I would probably calculate my expiry date in PHP and just add a simple where to the query. In Laravel that could look something like this:
$expireTreshold = Carbon::now()->addDays(90);
$expireCount = $myModel->where('e_date', '<=', $expireTreshold)->count();
For getting the current date, you can use CURDATE(), CURRENT_DATE(), and NOW() any one of these functions would get the current date. While the DATEDIFF() will get the difference between two periods (start date to end date).
If you only need to get the expiry dates that fit the 90 days condition use this :
SELECT e_date
FROM tableName
WHERE
e_date >= NOW()
AND datediff(e_date, NOW()) <= 90
In the query, you're scanning for future dates (from the current date and forward) and then get the differences, if the differences is less than or equal to 90 days, then it'll be selected.
if you need to show how many days left to each user:
SELECT sno, datediff(e_date, NOW())
FROM test
WHERE
e_date >= NOW()
AND datediff(e_date, NOW()) <= 90
It will work fine.
SELECT count(*) FROM table WHERE e_date < CURDATE() - INTERVAL 90 DAY;
OR
SELECT count(*) FROM table WHERE e_date < NOW() - INTERVAL 90 DAY;
cheers :)
Try this:
$your_date = "2018-01-01";
query = 'SELECT COUNT(*)
FROM thetable WHERE e_date =
DATE_ADD($your_date, INTERVAL 90 DAY)';
This is a question, which I could not find answer to anywhere. Okay. here it is.
I have two date ranges (This month and the last month)
Last month - 01/01/2015 (January 1 2015) to 31/01/2015
This month - 01/02/2015 (1st Feb 2015) to 28/02/2015
Now, each month has weeks. I have a table with column created_at. I want to fetch all the records week-wise into an array (to plot a graph) with their corresponding sum(value) or count(value) .
So it will be something like this:
Last Month:
Week 1 - 25
Week 2 - 34
etc.
This Month:
Week 1: 55
Week 2: 56
etc.
The date is in this format in created_at: 2015-07-21 01:27:14 (Y-m-d H:i:s)
In MySql You can use WEEK() to get the number of the week (from 1 to 53)
O you can use WEEKDAY() or DAYOFWEEK() the first bigins on Monday the second on Sunday.
You can use them into a GROUP BY with HAVING
Something like:
SELECT count(*)
FROM `YourTable`
WHERE `created_at` >= '2015-10-01' AND `created_at`< '2015-11-01'
GROUP BY WEEK(`created_at`)
To use the workaround you found You need to do something similar:
create a table named "numbers" with a field "id" (autoincrement) and 31 rows (one for each day of a month)
Then use a query like this:
SELECT count(i.created_at)
FROM
(SELECT DATE_FORMAT(DATE_ADD('2015-12-01', INTERVAL -n.id DAY), '%Y-%m-%d') AS AllDays
FROM numbers n) AS DaysOfMonth
Left Join
YourTableName i
ON STR_TO_DATE(i.created_at, '%Y-%m-%d') = DaysOfMonth.AllDays
GROUP BY WEEK(AllDays)
(try to adapt it to your needs)
What you need to do is group by the week and then sum the values. Here's a simple example of how it might work:
SELECT DATE_FORMAT(created_at,'%Y-%V') as interval, SUM(units_sold) as total_sold
FROM sales
GROUP BY DATE_FORMAT(created_at,'%Y-%V')
What you'll be getting is the year ant week number (ex. 2015-50) and the sum from that interval.
A table like this:
+----+------------+---------------------+
| id | units_sold | created_at |
+----+------------+---------------------+
| 1 | 2 | 2015-01-01 09:00:00 |
| 2 | 4 | 2015-01-04 10:00:00 |
| 3 | 1 | 2015-01-12 12:00:00 |
| 4 | 4 | 2015-01-16 13:00:00 |
+----+------------+---------------------+
Would result to:
+----------+------------+
| interval | total_sold |
+----------+------------+
| 2015-01 | 6 |
| 2015-03 | 5 |
+----------+------------+
I think it is useful for you...
SELECT GROUP_CONCAT(id), COUNT(id) AS idcount,SUM(id) AS idsum,
MONTHNAME(order_created_date) AS month_name, WEEK(order_created_date)
AS weeks FROM orders GROUP BY WEEK(order_created_date)
i have this mysql table with the timetables the train with php,
Type (INT) | time_start | time_stop
1 | 09:31:00 | 09:34:00
1 | 09:43:00 | 09:47:00
1 | 09:55:00 | 09:58:00
1 | 10:07:00 | 10:10:00
1 | 10:33:00 | 10:36:00
1 | 10:45:00 | 10:47:00
1 | 10:57:00 | 11:00:00
1 | 11:12:00 | 11:15:00
1 | 11:35:00 | 11:38:00
(and it goes on..)
- "type" is the timetable type, cus it changes in the winter, summer, etc.
- "type" is INT, and "time_start" and "time_stop" are VARCHAR(8)
I would like to know the most efective way to get the 6 next "train times", acording to the time now.
Imagine, it's now 09:33:10, what I want to obtain is this ones:
1 | 09:43:00 | 09:47:00
1 | 09:55:00 | 09:58:00
1 | 10:07:00 | 10:10:00
1 | 10:33:00 | 10:36:00
1 | 10:45:00 | 10:47:00
1 | 10:57:00 | 11:00:00
If theres any change change i should do in the mysql table, i'm also open to your ideias.
Thanks in advance ;)
Miguel.
You simply could change the VARCHAR type to TIME type, and do a SQL request like
SELECT * FROM <yourtable> WHERE time_start > NOW()
The basic approach is this:
select *
from timetables tt
where tt.time_start > current time
order by tt.time_start
limit 6
There are two challenges with this. The first is midnight. Presumably, if the time is late in the evening, then you want trains in the early morning as well. The second is converting the times to the right format.
select *
from timetable tt
order by (t.time_start > time(now()) desc,
tt.time_start
limit 6
The trick is to move the where condition into the ordering clause. In effect, this starts the ordering at the current time and continues it after midnight. This allows you to select the six with wrapping.
The time() function should be doing the necessary conversion for the comparison.
Just convert your searched time to an int:
$char_time = '09:33:10';
$int_time = (int) str_replace(':','', $char_time);
and then construct your sql like this:
$sql = "SELECT *, CAST(REPLACE(time_start, ',', '') AS INT) as mytime
FROM yourtable WHERE mytime > $int_time
ORDER BY mytime LIMIT 6";
Basically what we do above is just casting your varchar time field to an int type, and using that for comparing, this is a good solution if you can't change your database fields to be of TIME type.
The query will be
SELECT * FROM table_name
WHERE time_start >=time(now())
LIMIT 6
I have a table with number of page views per day. Something like this:
+------+------------+------+----------+
| id | date | hits | mangaID |
+------+------------+------+----------+
| 4876 | 1331843400 | 132 | 13 |
+------+------------+------+----------+
| 4876 | 1331929800 | 24 | 236 |
+------+------------+------+----------+
| 7653 | 1331929800 | 324 | 13 |
+------+------------+------+----------+
I'm trying to get sum hits from last week with the below code:
SELECT sum(hits) as hits FROM om_manga_views WHERE DATE_SUB(CURDATE(),INTERVAL 1 week) <= date and mangaID = '13'
My problem is that I'm storing date as time using strtotime in date's field as int type.
So how can i get what i want!?
Try this:
select sum(hits) hitCount from t
where from_unixtime(date) >= current_date() - interval 1 week and mangaId = 11
Here is the fiddle to play with.
I slightly changed your data because the records you provided are older than 7 days, so the sum would return 0.