Splitting month into weeks and using GROUP BY - php

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)

Related

Get the count of users before 90 days records from the e_date

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)';

mysql select sort by day and time str_to_date

I have a mysql table as
Table: orders
Order | day | time
1 | Tuesday 31-10-2017 | 10:00 AM
2 | Thursday 02-11-2017 | 11:00 AM
3 | Tuesday 31-10-2017 | 01:00 PM
4 | Tuesday 31-10-2017 | 10:00 AM
5 | Sunday 29-10-2017 | 09:30 AM
I need to sort orders based on day and time , for example:
Order | day | time
5 | Sunday 29-10-2017 | 09:30 AM
1 | Tuesday 31-10-2017 | 10:00 AM
4 | Tuesday 31-10-2017 | 10:30 AM
3 | Tuesday 31-10-2017 | 01:00 PM
2 | Thursday 02-11-2017 | 11:00 AM
tried:
select * from request ORDER BY STR_TO_DATE(time,'%h:%i%p') asc, STR_TO_DATE(day,'%l %d-%m-%Y') desc
but thats not sorting as expected...
Really, you should store dates using internal date formats, not as a string. You can readily get the date of the week using date/time functions.
Your date format makes this even harder, but you can do:
order by str_to_date(substring_index(day, ' ', -1), '%d-%m-%Y'),
str_to_date(time,'%h:%i%p')
Now that you've fixed this problem, go back to your data and do:
alter table orders add column orderdate datetime;
update orders
set orderdate = addtime(str_to_date(substring_index(day, ' ', -1), '%d-%m-%Y'),
str_to_date(time,'%h:%i%p'));
Check that orderdate is correct. Then do:
alter table orders drop column day;
alter table orders drop column time;
Isn't that nice? Your data is now fixed.
First, you should order the more important column first. So the order of the order statements should be;
ORDER BY STR_TO_DATE(day,'%l %d-%m-%Y') desc, STR_TO_DATE(time,'%h:%i%p') asc
And the day column should be ordered asc, not desc;
ORDER BY STR_TO_DATE(day,'%l %d-%m-%Y') asc, STR_TO_DATE(time,'%h:%i%p') asc
By the way, I think the pattern of the day of the week should be %W instead of %l;
ORDER BY STR_TO_DATE(day,'%W %d-%m-%Y') asc, STR_TO_DATE(time,'%h:%i%p') asc
I tried here;
http://sqlfiddle.com/#!9/f8fdbf/11/0
Following query will work:
select * from request
ORDER BY STR_TO_DATE(SUBSTRING_INDEX(day,' ',-1),'%d-%m-%Y'),
STR_TO_DATE(time,'%h:%i%p') desc,

How to get Sale data of every month of a year

I'm trying to get Sale Data of every month of particular year, but I'm having a problem building a query for it.
Here is What I've tried
SELECT COUNT(`id`) AS `total_order`
FROM orders
WHERE date BETWEEN ? AND ?
GROUP BY `total_order`
HERE is How my table look like
----------------------------------------
| id | item_name | amount | time |
| 21 | item_1 | 10 | 1506675630 |
| 22 | item_2 | 30 | 1506675630 |
| 23 | item_3 | 70 | 1506675630 |
| 24 | item_4 | 100 | 1506675630 |
----------------------------------------
Now here is what i want from the query
1 - Total Sales amount made from the beginning of the year till today.
2 - Sales made Today
3 - Sales made in Last Month
4 - Sales Made in Last 3 month
5 - Sales Made in Last 6 Month
6 - Total Number of Sales made in every month of this particular year
for e.g -
January - 20
Feb -100
March - 200 & so on.
How can i achieve this complex query?
SELECT `id` AS `Order_Number`, item_name, SUM(Amount)
FROM orders
WHERE time >= '01/01/17'
GROUP BY date
That would give you your first result. Try the others and let me know what you get
This answers your first question
SELECT
DATE_FORMAT(FROM_UNIXTIME(time), '%Y-%m') as interval,
COUNT(*) AS sales_made,
SUM(amount) AS sales_amount
FROM orders
WHERE
time BETWEEN UNIX_TIMESTAMP('2017-01-01') AND UNIX_TIMESTAMP('2018-01-01')
GROUP BY 1
ORDER BY 1;
Here is what i think would work:
for the first 5 queries try something like this.
SELECT SUM(amount)
FROM orders
WHERE DATE_FORMAT(FROM_UNIXTIME(`orders.time`), '%Y-%m-%d') BETWEEN ? AND ?
And for the last one you'll need :
SELECT DATE_FORMAT(FROM_UNIXTIME(`orders.time`), '%Y-%m-%d') AS 'date', SUM(amount)
FROM orders
WHERE date between ? AND ?
GROUP BY DATE_FORMAT(date, '%Y%m')
You can try without the FROM_UNIXTIME if it doesnt work.

Getting and comparing averages from MySQL with PHP

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

MySQL query to retrieve maximum number of items within a given time period

I've a table like attached.
I want to find the "number of items in a certain month which has maximum entries in the database".
For instance, Jan has 10 entries, Feb has 13 entries, Mar has 8 entries.
I want to find the the number 13 for Feb from the database as it has the max entries. How do I check the time range in the query?
You can group all of your realeasedates by month and year to get a count like this:
SELECT MONTH(releasedate) AS month, YEAR(releasedate) as year, count(r_id) AS number
FROM my_table
GROUP BY YEAR(releasedate), MONTH(releasedate)
ORDER BY YEAR(releasedate), MONTH(releasedate)
This'll give you something like this:
+--------+--------+--------+
| month | year | number |
+--------+--------+--------+
| 1 | 2013 | 13 |
| 2 | 2013 | 8 |
Then you could select the maximum like this:
SELECT MONTH(releasedate) AS month, YEAR(releasedate) as year, count(r_id) AS number
FROM my_table
GROUP BY YEAR(releasedate), MONTH(releasedate)
ORDER BY count(r_id)
LIMIT 1
Which'll give you:
+--------+--------+--------+
| month | year | number |
+--------+--------+--------+
| 4 | 2013 | 19 |
+--------+--------+--------+
Which'll represent the highest month
SELECT COUNT(*) FROM `mytable` WHERE releasedate >= DATE '2013-02-01' AND releasedate <= DATE '2013-02-28'
That should work
EDIT:
As suggested by lafor...
WHERE YEAR(releasedate)=2013 AND MONTH(releasedate)=2
should also work

Categories