How to get Sale data of every month of a year - php

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.

Related

Joining a calendar table to a sales table to get total sales for every day in a specified range

I have a 'sales' table called phpbb_sold which records each 'sale' as a row.
I am able to use a WHERE clause with the uitemid field to select one particular item in the sales records, as seen below:
SELECT uitemid, locktime, migrated_sold FROM phpbb_sold WHERE uitemid=342;
+---------+------------+---------------+
| uitemid | locktime | migrated_sold |
+---------+------------+---------------+
| 342 | 1632523854 | 1 |
| 342 | 1634239244 | 1 |
| 342 | 1634240072 | 1 |
| 342 | 1636367271 | 1 |
+---------+------------+---------------+
uitemid = number that identifies this as a sale of X item. locktime = UNIX timestamp that shows the datetime that the item was sold. migrated_sold = the quantity of the item sold. So this is nice, I have a table that keeps a record of each sale as it happens.
What I want to achieve though, is a record of the total number of sales of this item type, for each day in a 6 month period spanning back from the current date, and including each day regardless of whether a sale was made or not. So the desired output of my query would be:
SELECT (the query I want goes here) and returns the following rows...;
+------------+------------+
| caldate | sold_total |
+------------+------------+
| 2021-09-23 | 2 |
| 2021-09-24 | 0 |
| 2021-09-25 | 1 |
| 2021-09-26 | 0 |
| 2021-09-27 | 0 |
| 2021-09-28 | 1 |
+------------+------------+
Note that each day is included as a row in the results, even where the sales total for that day is 0. I read that to do this, I would be required to create a calendar table with one column and all the days I want as rows, so I went ahead and did that:
SELECT caldate FROM phpbb_calendar;
+------------+
| caldate |
+------------+
| 2021-09-23 |
| 2021-09-24 |
| 2021-09-25 |
| 2021-09-26 |
| 2021-09-27 |
| 2021-09-28 |
+------------+
Now all that remains is for me to make the query. I need to somehow return all the rows from the phpbb_calendar table, joining the data from sum() (?) of the total migrated_sold for those days where exists, and a 0 where no sales took place.
I anticipated some issues with the UNIX timestamp, but it's okay because I am able to get caldate and locktime fields to be the same format by using from_unixtime(locktime, '%Y-%m-%d'), so both dates will be in the YYYY-MM-DD format for comparison.
Please could someone help me with this. I've gotten so close every time but it seems that everyone else's request is only slightly different from mine, so existing questions and answers have not been able to satisfy my requirements.
End goal is to use a JS chart library (AnyChart) to show a line graph of the number of sales of the item over time. But to get there, I first need to provide it with the query necessary for it to display that data.
Thanks
Update
Using this query:
SELECT c.caldate, u.uitemid, sum(v.migrated_sold) as total_sales
from phpbb_calendar c cross join
(select distinct uitemid from phpbb_sold) u left join
phpbb_sold v
on c.caldate = from_unixtime(v.locktime, '%Y-%m-%d') WHERE u.uitemid = 39 and c.caldate <= curdate() GROUP BY c.caldate ORDER BY c.caldate;
Returns:
But as you can see, it's just tallying up the total number of sales ever made or something - its clearly incrementing in a way I don't understand.
I don't want it to do that - I want it to count the number of total sales on each day individually. The results should look like this:
So that what is returned is basically a 'histogram' of sales, if any occurred, including 'empty' days where there were no sales (so these empty days must still be returned as rows).
SELECT c.caldate, u.uitemid, COALESCE(SUM(v.migrated_sold), 0) AS total_sales
FROM phpbb_calendar c
CROSS JOIN (SELECT DISTINCT uitemid FROM phpbb_sold WHERE uitemid = 37) u
LEFT JOIN phpbb_sold v
ON v.locktime BETWEEN UNIX_TIMESTAMP(TIMESTAMP(c.caldate)) AND UNIX_TIMESTAMP(TIMESTAMP(c.caldate, '23:59:59'))
AND u.uitemid = v.uitemid
WHERE c.caldate BETWEEN CURDATE() - INTERVAL 6 MONTH AND CURDATE()
GROUP BY c.caldate, u.uitemid
ORDER BY c.caldate;
N.B. I have changed your join to use the unix_timestamp as it should be more efficient and it can use any existing index on locktime
check this out:
select id, d, sum(s) from (
select U.id, d, 0 s from (
select adddate(current_date(),-rows.r) d from (
select (#row_number := #row_number + 1) r
from information_schema.columns,
(SELECT #row_number := 0) AS x
limit 200
) rows
) dates,
(SELECT distinct uitemid id FROM `phpbb_sold`) U
where d > adddate(current_date(), interval -6 month)
union
select uitemid, date(from_unixtime(locktime)),sum(migrated_sold)
from `phpbb_sold`
group by uitemid, date(from_unixtime(locktime))
) sales_union
group by id, d
order by id, d;
see dbfiddle
no need for calendar table

Splitting month into weeks and using GROUP BY

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)

Counting renewals during count of subscription sold

I've a table in which write every subscription sold of my magazine, like this:
USERID | DATE |
31 | 2011-09-22 |
54 | 2011-09-22 |
59 | 2011-09-23 |
11 | 2011-10-02 |
88 | 2011-10-05 |
31 | 2011-10-06 |
17 | 2011-10-12 |
54 | 2011-10-15 |
31 | 2011-11-05 |
54 | 2011-11-12 |
Now, for statistical purpose, i need to having an outcome in which i see, for every single month, how many subscriptions i've sold and how many users have already bought once this.
For instance, if we look the datas on top, i should have an outcome likie this:
DATE | SOLD | RENEWAL
09 | 3 | 0
10 | 5 | 1
11 | 2 | 2
I can to group the subscriptions sold monthly, but i can't add the "renewal" info.
SELECT COUNT( * ) AS sold, MONTH(date) FROM table_sold WHERE date >= CURDATE() - INTERVAL 13 MONTH GROUP BY YEAR( date ) , MONTH( date ) ORDER BY date ASC LIMIT 1,15
In this way i only have an outcome like this:
DATE | SOLD
09 | 3
10 | 5
11 | 2
I've tried several option, with subquery, union and so on, but without successful.
There is to consider that the table has 70.000 entries and a query with a hard scan could be a problem.
In your opinion is there a way in mysql or i've to take the idea to make it in php?
Here is an idea. Look at the first date for each user. Then count renewals in every month that is not the first date:
select year(date), month(date), count(*) as sold,
sum(case when date <> firstdate then 1 else 0 end) as renewals
from subscriptions s join
(select userid, min(date) as firstdate
from subscriptions s
group by userid
) su
on s.userid = su.userid
group by year(date), month(date)
order by year(date), month(date);

Count all unique records

I have a database with the following format:
myTable
productgroupID | productID | views | date
1 | 10 | 25 | 2013-05-23
4 | 105 | 15 | 2013-05-23
7 | 60 | 65 | 2013-05-23
7 | 60 | 55 | 2013-05-22
7 | 60 | 45 | 2013-05-21
Now I want to sum all views of a product in the moth May.
Result should be:
productgroupID | productID | viewed | month
7 | 60 | 165 | 2013-05-01
1 | 10 | 25 | 2013-05-01
4 | 105 | 15 | 2013-05-01
I tried the query below, but this gives me all views of a specific productgroupID. But I need the sum of the unique productgroupID & productID.
SELECT COUNT( views ) AS viewed, productgroupID FROM product_stats_daily GROUP BY productgroupID
If you want the views totaled, then you can use the sum() aggregate function and then you can group by the month and year for the date:
select productGroupId,
productId,
sum(views) viewed,
month(date) Month,
year(date) Year
from myTable
group by productGroupId, productId, month(date), year(date);
See SQL Fiddle with Demo
You could also use Date_Format to get the date in the format that you want:
select productGroupId,
productId,
sum(views) viewed,
DATE_FORMAT(date, '%Y-%m-01') date
from myTable
group by productGroupId, productId, DATE_FORMAT(date, '%Y-%m-01')
See SQL Fiddle with Demo
COUNT will count number of rows while SUM will sum up value of retrieved rows.
So your query becomes:
SELECT SUM( views ) AS viewed, productgroupID
FROM product_stats_daily
GROUP BY productgroupID
There's probably a more elegant way to force the date to the beginning of the month, but this should work:
SELECT
ProductGroupID,
ProductID,
SUM(views) AS viewed,
DATE_FORMAT(date, '%Y-%m-01') AS Month
FROM myTable
GROUP BY
ProductGroupID,
ProductID,
DATE_FORMAT(date, '%Y-%m-01')

MySQL query to omit records, while searching, after X amount of Days

I am using the following query,
SELECT
b.sales_id,b.category_id,a.bus_title,b.sales_title,b.sale_starts,b.sale_ends
FROM tbl_sales b INNER JOIN tbl_business a
ON a.bus_id=b.bus_id
WHERE b.active=1
AND CURDATE( ) < DATE_ADD(b.sale_ends, INTERVAL 14 DAY )
AND b.category_id='16' OR b.category_id
IN (SELECT cat_id FROM tb_category WHERE parent_id=16)
ORDER BY (b.sale_ends=CURDATE()) DESC,(b.sale_ends>CURDATE()) DESC,b.sale_ends ASC
and getting the result as shows below,
sales_id | category_id |bus_title | sales_title|sale_starts|sale_ends
----------|-------------|------------|------------|-----------|----------
36 | 17 | my bus | my sale |2012-04-03 |2012-05-03
35 | 19 | my bus 1 | my sale 1 |2012-04-03 |2012-05-03
42 | 16 | my bus 12 | my sale 12 |2012-04-05 |2012-05-05
10 | 17 | my bus 123| my sale 123|2011-12-15 |2011-12-18
I need to omit(not delete) sales after X amount of days past the End Date (here after 14 days). But the MySQL query i had written above returns the wrong results and displays the records with End Date 2011-12-18. How can i write the query in an effective way.
Need help. Thanks in advance.
Add this to your query :
AND sale_ends < DATE_SUB(NOW(), INTERVAL 14 day)

Categories