I'm trying to find the average of net total for a given month, based on previous years to help show things like seasonal trends in sales.
I have a table called "Invoice" which looks similar to the below (slimmed down for the purpose of this post):
ID - int
IssueDate - DATE
NetTotal - Decimal
Status - Enum
The data I'm trying to get, for example would be similar to this:
(sum of invoices in June 2018 + sum of invoices in June 2019 + sum of invoices in June 2020) divided by number of years covered (3) = Overall average for June
But, doing this for the full 12 months of the year based on all the data (not just 2018 through to 2020).
I'm a bit stumped on how to pull this data. I've tried subqueries and even tried using a SUM within an AVG select, but the query either fails or returns incorrect data.
An example of what I've tried:
SELECT MONTHNAME(`Invoice`.`IssueDate`) AS `CalendarMonth`, AVG(`subtotal`)
FROM (SELECT SUM(`Invoice`.`NetTotal`) AS `subtotal`
FROM `Invoice`
GROUP BY EXTRACT(YEAR_MONTH FROM `Invoice`.`IssueDate`)) AS `sub`, `Invoice`
GROUP BY MONTH(`Invoice`.`IssueDate`)
which returns:
I see two parts to this query, but unsure how to structure it:
A sum and count of all data based on the month
An average based on the number of years
I'm not sure where to go from here and would appreciate any pointers.
Ideally, I'd want to get the totals from rows where "Status" = "Paid", but trying to crack the first part first. Walk before running as they say!
Any guidance greatly appreciated!
Basically you want two levels of aggregation:
SELECT mm, AVG(month_total)
FROM (SELECT YEAR(i.IssueDate) as yyyy, MONTH(i.issueDate) as mm,
SUM(i.`NetTotal`) as month_total
FROM Invoice i
GROUP BY yyyy, mm
) ym
GROUP BY mm;
Just for the Average Amount Part You Could use a query like
Select Date From Your_Table Where Date Like '20__-06-%'
You can arrange it into asc desc order.
Related
A bit unfamiliar with this but wondering how I can use a similar function on SQL as this Google Sheets function to pull "average" monthly revenue based on the start_date a product started selling.
=iferror(H200DATEDIF(VLOOKUP($A172,'DATA'!$A$2:$H$1000,13, false),TODAY(),"M"),0)
on SQL, if I were to want to pull the average monthly revenue from TODAY and by the number of months the product has been released, how would that look instead?
So far, I have:
SELECT
`product`.`id` AS `id`,
DATE_FORMAT(`product`.start_selling_date, "%m/%d/%Y") AS `release_day`,
`product`.`revenue` as `rev`,
FROM `product`
The goal would be to take the rev part which gives me total revenue and divide it by the number of months it's been since the release_day.
Example:
Product A launched on 2022-01-21 and has $10,000 in revenue. The average monthly would be around $1,428.57 (7 months). If it's possible to have SQL calculate that automatically when pulling the rest of the information (product ID, release_day, revenue, average monthly revenue)
Is it maybe something like DATEDIFF?
Thank you!
Yes, DATEDIFF(). Assuming the date field is an actual date or datetime field, something like...
SELECT
product.revenue / ( DATEDIFF( CURDATE(), product.start_selling_date ) / 30 ) AS average_monthly_revenue
I am using 30 day months here, but you could get more accurate if needed.
So I'm counting articles per year/month between the start of the year and the current time:
SELECT Year(FROM_UNIXTIME(date)) as year
, Month(FROM_UNIXTIME(date)) as month
, Count(*) as `total`
FROM articles
WHERE date BETWEEN UNIX_TIMESTAMP(DATE('2017-01-01 00:00:00')) AND UNIX_TIMESTAMP(DATE('2017-05-17 12:00:05'))
GROUP
BY Year(FROM_UNIXTIME(date))
, Month(FROM_UNIXTIME(date))
The only issue, is that months that have zero, won't show up.
Is there an easy way around it?
The best solution I can think of is to do an inner join with a lookup table that has months 1-12 in them. Thus verifying there will always be a 12 month result set?
Possibly including a restriction for the current date month can not be surpassed, so you don't actually always get for the whole year.
look here:
Include missing months in Group By query
I am sure this is pretty simple but I cannot figure out what I am doing incorrectly here. I am trying to get totals for certain fields over the last 7 days and group them by date and field.
Example:
The following table:
TABLE API_LOG
COLUMNS
customer
ip_address
date_logged
endpoint
So I would like to get the total endpoint calls for the last 7 days per customer and ip_address. I already have the daily totals organized but for some reason cannot get this to group correctly.
SELECT date_logged AS DATE_LOG, Customer,
COUNT(customer) AS CustomerCount, COUNT(ip_address) as IPCOUNT
FROM API_log
GROUP BY date_logged, Customer
The idea is then to bind this to a chart.
Sample data:
Expected output;
Current Output:
Appreciate assistance with this.
edit:
I group by date because I want to see the total for each day for the last 7 days. In other words, give me the total counts for each customer by day.
I think your date_logged column is datetime so it makes sense that you are getting separate dates when grouping. Try this
SELECT CAST(date_logged AS DATE) AS DATE_LOG, Customer,
COUNT(customer) AS CustomerCount, COUNT(ip_address) as IPCOUNT
FROM API_log
GROUP BY CAST(date_logged AS DATE), Customer
I'm in need of some help structuring in-time queries. There's a few of them I need - but I think that if I can be shown how to do one, I can figure out the others.
What I'm after:
-Rolling 12 month view of 'inactive accounts'...ie number of accounts that have not placed an order in the 12 months prior.
-This ideally will be a subquery (in a much larger script) joining back on to a dates table (see below)
January 2015 | # of customers with no orders from 1/2014-1/2015
February 2015 | # of customers with no orders from 2/2014-2/2015
March 2015 | # of customers with no orders from 3/2014-3/2015
etc...
What I'm having trouble wrapping my mind around is how I'd structure a where clause to ensure that it scans all orders and only returns the total of account ID's that had not placed an order in the year prior to that month. I've used different combinations of DATEDIFF, DATESUB etc.
SELECT DATE_FORMAT(order_datetime, '%Y-%m'), COUNT DISTINCT (account_id)
FROM warehouse.orders
JOIN warehouse.accounts ON xyz
WHERE...
It feels like I'm on the right path - I just keep mentally going in circles trying to figure this out.
Cheers and thanks in advance.
I don't have enough reputation points to simply comment on your question. I don't fully understand it though.
Are you using SQLServer/TSQL or MySQL?
Do you want to have just one column which calculates the last 12 months' rolling average or 12 columns for the rolling average each month? If it is just one figures for the last 12 months tolling do you want that to be from the current day or the beginning of that month?
If it was SQL Server and a rolling 12 months to now, the calculation could be:
SELECT SUM(CASE WHEN DATEDIFF(y,GETDATE(),order_date_time) < 1 THEN COUNT(DISTINCT account_id) END) as January2015
If you're using MySQL replace GETDATE() with NOW()
If you want one value rolling but to the beginning of the month then you could use:
SELECT SUM(CASE WHEN DATEDIFF(y,DATEADD(M, DATEDIFF(M, 0, GETDATE()), 0),order_date_time) < 1 THEN COUNT(DISTINCT account_id) END) as January2015
If I've missed the point entirely, please let me know and I'll happily amend the answer
You should query between dates, in order to get the count of events for each id.
select case
when count(account_id)<0 then 'INACTIVE'
when count(account_id)>0 then 'ACTIVE'
from warehouse.orders
where data_format(order_datetime, '%m/%Y') between '1/2014' and '1/2015'
group by account_id)
I am having trouble understanding the structure of the query i wish to perform. What i have is a large set of data in a table with multiple UnitID's. The units have temperatures and Timestamps of when the temperatures where recorded.
I want to be able to display the data where I can see the Average temperature of each unit separated in a weekly interval.
Apologies for my previous post, I'm still a novice with querying. But i will show you what i have done so far.
SELECT UnitID AS 'Truck ID',
AVG(Temp) As 'AVG Temp',
LogTime AS 'Event Time',
DAY(g.`LogTime`) as 'Day',
MONTH(g.`LogTime`) as 'Month',
COUNT(*) AS 'Count'
FROM `temperature` as g
WHERE DATE_SUB(g.`LogTime`,INTERVAL 1 WEEK)
AND Ana > 13 AND Ana < 16 AND NOT g.Temp = -100
GROUP BY 'truck id', YEAR(g.`LogTime`),MONTH(g.`LogTime`),WEEK(g.`LogTime`)
Order BY 'truck id', YEAR(g.`LogTime`),MONTH(g.`LogTime`),WEEK(g.`LogTime`)
;
(Sorry, I don't know how to display a table result at the moment)
This result gives me the weekly temperature averages of a truck, and shows me on which day of the month the temperature was recorded, as well as a count of temperatures per week, per truck.
The Query I want to perform , creates 5 columns, being UnitID, Week1, Week2, Week3, Week4.
Within the 'Week' columns I want to be able to display a weekly(Every day of the Week) temperature average for each truck, where the following week is set a week after the previous week (ie. Week2 is set to display the avg(temp) one week from Week1).
And this is where I am stuck on the structure of how to create the query. Im not sure if i need to create sub-queries or use a Union clause. I have tried a couple of queries , but i have deleted them because they did not work. I'm not sure if this query is too complex or if its even possible.
If anyone will be able to help I would greatly appreciate it. If there is any other info I can supply that will help, I will try to do so.
Hopefully this is solvable. :p
MySQL has a WEEK function that will return the week of the year as an integer (0-52). You can use that in you GROUP BY clause, and then use the AVG aggregation function to get the average temperature. Your query would look something like this:
SELECT unitID, WEEK(dateColumn) AS week, AVG(tempColumn) AS averageTemperature
FROM myTable
GROUP BY unitID, WEEK(dateColumn);
Here is a list of other helpful Date and Time Functions that may be useful for querying your database.