Is it possible to loop in MySQL for sales data? - mysql

I am trying to build a useful query for our sales team to see how many sales our business has made in the current month, compared to the same point in the previous months.
So if today is the 14th of September, I want to compare how many sales we'd made between 1st - 14th of August and so on to see if we are up or down.
I have created the query to pull the data, but it's not in any kind of loop. Can anyone suggest a way to do this please? Below shows me the data for July 2015...
SELECT CONCAT(MONTH(OrderDate),'-',YEAR(OrderDate)) AS MontyYear,
COUNT(sw_orders.OrderNumber) OrderCount,
SUM(Gross) GrossIncome
FROM
orders
WHERE
orders.MasterOrderNumber = ''
AND Date(OrderDate) >= '2015-07-01'
AND Date(OrderDate) <= Concat('2015-07-', DAY(CURDATE()))
order by orders.ordernumber;
It feels like I need a variable that is the month number, so starts at "1" for January - then counts up per loop and use is used in the OrderDate part of the query?

I would not use string literals in the query, but make use of MySql's DAY and MONTH function:
WHERE orders.MasterOrderNumber = ''
AND DAY(OrderDate) <= DAY(CURDATE())
GROUP BY MONTH(OrderDate)

Related

SSRS 2008 R2 Report. Change month grouping from calender month

I have a report that outputs relatively simple counts of clients. It outputs everything from a system as data parameters are not required. They want to see everything.
The thing that is throwing me is, they want months grouped by the 24th of one month to the 23th of the next month.
For example, the month of October 2016 should count all data between the 24th October 2016 TO 23rd of November 2016, the previous Septeber should group everthing between 24/09/2016 to 23/10/2016 etc etc.
In short, is it possible to group month using 24th of that month to the 23rd of the next month?
Happy to provide more information, a bit new to advanced ssrs tasks like this. I did search for solutions like this but couldnt find anything suitable. Any help greatly appreciated.
This requirements can be implemented by enhancing your query. Say f.e., you have the following:
select
t.Date,
t.AggregatedField
from SomeSchema.SomeTable as t
You can do next:
select
MonthNumber =
case
when DATEPART(DAY, t.Date) >= 24 then DATEPART(MONTH, t.Date)
else DATEPART(MONTH, t.Date) - 1
end,
t.AggregatableField
from SomeSchema.SomeTable as t
The output you will get will be like (month_number, field_to_aggregate). You then need to group data by that month_number, you can do that directly in SQL, or using RDL report grouping (consider that first provides the best performance).
To construct month name, you will probably need to extract year number to like this:
DATEPART(YEAR, t.Date)
and then construct date using month number anhd year number.

Selecting 'DATE' fields in mysql by month and day with comparison

Trying to select a closest previous and next holiday from the database. Say, New Year's Day is always at the 1st of January, and New Year's Eve is at the 31st of December. Current year is completely irrelevant, so I'm trying to select previous holiday by day and month (New Year's Eve) with the following MySQL query:
SELECT * FROM `calendar` WHERE DATE_FORMAT(`holidayDate`, "%m-%d") < "01-01"
It gives NULL. I was expecting that it would drop through and will look in the previous month, December, but...
Tried a lot of different ways of doing it, but still no success.
P.S.: Cannot use TIMESTAMP in this case...
The reason it's returning null is because there isn't anything less than '01-01'. The query doesn't wrap around to the beginning.
What I would do is write a case statement that checks to see if you are at the earliest holiday.
If you are the earliest holiday, then you can select the latest holiday (a way of wrapping around).
If you are not the earliest holiday, then you need to select the one before it. I did this by ordering them in descending date, and limiting it to 1. (Effectively grabbing the holiday occurring before the current date.)
Try this:
SELECT *
FROM calendar
WHERE
CASE WHEN DATE_FORMAT(CURDATE(), '%m-%d') = DATE_FORMAT((SELECT MIN(c.holidayDate) FROM calendar c), '%m-%d')
THEN holidayDate = (SELECT MAX(c.holidayDate) FROM calendar c)
ELSE
DATE_FORMAT(holidayDate, '%m-%d') < DATE_FORMAT(CURDATE(), '%m-%d')
END
ORDER BY holidayDate DESC
LIMIT 1;
Here is an SQL Fiddle example. I created two queries. One that uses the current date (seen above) and one that has Jan 1st hard coded to show that the case statement does work. I've only added certain holidays to test.
If two queries are acceptable for you:
SELECT max(holidayDate) as prev_holiday from calendar where holidayDate < now();
SELECT min(holidayDate) as next_holiday from calendar where holidayDate > now();

Trying to find this day last year. Ex: Get the 1st Friday of October, not the October the 4th

I'm not sure this is even possible without using PHP, but I'd love to try.
I have a database that looks like this (a bunch of other stuff, but this is all that is relevant:
Date_Day (is a range from 1 to 31 with no trailing 0)
Date_Month (is a range from January to December, not numerical)
Date_Year (is the year in 4 digit format, ex: 2005)
Total (number with 2 decimal places)
I know the way the dates are stored is awful, but this is the database I was given. If there is a query that I could use these columns to create an actual DATETIME column, I would happily do it, I just don't know what that query looks like.
I have this query that returns the Total sales amount for this day for all previous years:
SELECT
Date_Year, Date_Month, SUM(Total)
FROM
tablename
WHERE
Date_Year < YEAR(CURDATE())
AND
Date_Month = MONTHNAME(CURDATE())
AND
Date_Day = DAY(CURDATE())
GROUP BY
Date_Year, Date_Month
So if I run this today, I get the daily totals for October 4th for all previous years. The issue is that in sales, this isn't very helpful for comparing growth. What I really need is the daily totals for the 1st Friday in October for all previous years.
Is this possible without having to rely on PHP? If so, I would be very grateful for your help.
Thank you.
You might be looking for DAYOFWEEK()
Returns the weekday index for date (1 = Sunday, 2 = Monday, …, 7 = Saturday). These index values correspond to the ODBC standard.
mysql> SELECT DAYOFWEEK('2007-02-03');
> 7
SELECT
Date_Year, Date_Month, SUM(Total)
FROM
tablename
WHERE
Date_Year < YEAR(CURDATE())
AND
Date_Month = MONTHNAME(CURDATE())
AND
Date_Day = DAY(LAST_DAY(CURDATE()) - ((28 + WEEKDAY(LAST_DAY(CURDATE())) - 4)))
GROUP BY
Date_Year, Date_Month
maybe this will help

MySQL Query to group by date range?

I've got a table in MySQL that shows me number of hours logged on a daily basis. I'm trying to build a view that will allow me to quickly group my data by blocks/range of days. The simplest case would be on a monthly basis which wouldn't be difficult. I could just select the date as "%y-%m" and then group by that column.
Ex:
select time_logged, date_format(start_date, '%Y-%m') AS `month_logged`
from work_log
group by month_logged
That works fine if I am just grouping by month. But my issue is that I need to group from the 13th of the month to the 12th of the following month (ex: July 13-Aug 12, Aug 13- Sept 12, etc).
Is there an easy way to do something like that in a single query/view? I can't seem to come up with a query that works for my needs, even playing with the different date field combinations.
Subtract 13 days and do the grouping you are doing now:
select time_logged,
date_format(start_date - interval 12 day, '%Y-%m') AS `month_logged`
from work_log
group by month_logged;

SQL fiscal quarter totals... I've already got the calendar ones

Here's the SQL query I have for the calendar year's quarterly totals
SELECT
SUM(CASE WHEN WEEK(LAST_DAY) <= 13 THEN BILLABLE END) AS Q1
,SUM(CASE WHEN WEEK(LAST_DAY) >= 14 AND WEEK(LAST_DAY) <= 26 THEN BILLABLE END) AS Q2
,SUM(CASE WHEN WEEK(LAST_DAY) >= 27 AND WEEK(LAST_DAY) <= 39 THEN BILLABLE END) AS Q3
,SUM(CASE WHEN WEEK(LAST_DAY) >= 40 AND WEEK(LAST_DAY) <= 53 THEN BILLABLE END) AS Q4,
Emp_Name
FROM 'emp_info'
WHERE YEAR(LAST_DAY) = YEAR(CURRENT_TIMESTAMP)
GROUP BY Emp_Name
I need to shift it so it gives me the fiscal year (July 1 to June 30) totals.
I know when doing so the week numbers will need to start on July 1, not January 1 and there'll probably be a case statement in there somewhere. But I can't get it to come out correctly.
If I were you, I'd store fiscal quarters in a table. Then your queries would be dead simple. And not only would they be dead simple, it would be obvious when they were correct.
Try this query -
SELECT
Emp_Name,
IF(DATE(LAST_DAY) <= DATE('2011-6-30'), YEAR(LAST_DAY) - 1, YEAR(LAST_DAY)) f_year,
QUARTER(LAST_DAY) quarter,
SUM(BILLABLE)
FROM
emp_info
GROUP BY
Emp_Name,
f_year,
quarter;
You are aware that your query doesn't divide year into 4 quarters by month? Instead of using the WEEK() function use MONTH().
By operating on months and years (YEAR()) calculating sum for fiscal year will be easy.
Your real problem is going to be that generally speaking, date and time functions will only work on ISO/(Other common) calendar date/time objects, but you need them to work on a company-specific fiscal calendar.
This is why Calendar files are used, as a translation between fiscal and ISO calendars.
Generate your calendar fileout for a few years in either direction, then you can join to it, restricting/grouping by fiscal year and period. No case statements needed.
I also recommend storing most dates in your tables as actual ISO dates, then only translating/using fiscal dates when actually necessary - we have some summation tables here which are keyed off fiscal year/period, but which display shopping-behaviour data to customers (who don't know/care when our fiscal year is)...