I'm trying to provide a rolling 12 month view of our 'dormant' clients by region each month (dormant = haven't placed an order in past 12 months). Below is stripped down piece of the script (minus the necessary joins).
select region, count(clientID)as TotalDormant
FROM clients
WHERE test_account = 'NO'
AND DATEDIFF(curdate(), last_order_date) > 365
GROUP BY 1
Returning...
Region Total Dormant
ROW 500
US 1000
However...because of the curdate() it's only returning the dormant customers who have been inactive for a full year leading up to today (9/17/2015). I need it to return the number of dormant clients we had on each of the past 11 months.
Any help on what I'll need to do to return the number dormant for each month on a rolling 12m basis by region?
I have tried inner join, subqueries etc...but they all wind up messing up even septembers data (which is accurate using the basic query above). So I decided to strip it down, ask for advice, and build from there.
Use the DATE_FORMAT function to get your month in the date:
select region, count(clientID) as TotalDormant,
DATE_FORMAT(last_order_date,'%Y %m') AS dormantSince
FROM clients
WHERE test_account = 'NO'
AND DATEDIFF(curdate(), last_order_date) > 365
GROUP BY DATE_FORMAT(last_order_date,'%Y %m');
When also placed in the GROUP BY, the query will give your the dormance since a certain month.
Related
I have a table of cellular invoices, relevant columns are Cellular_Account_id (INT), billing_end_date(DATE), and data_usage_GB.
There is a separate row for each account every month. I'm trying to get a list of accounts that have had no data usage for each of the past three months.
I'm pretty new to databases in general, so I'm not really even sure what syntax I should be searching for, or what approach I should be taking.
I can, of course, select WHERE data_usage_GB = 0.000 AND MONTH(billing_end_date) = month(current_date()) -1 but that only gives me the info in 1 month's range. I'm not sure how to group together the results where data_usage_GB = 0.000 for each of the last three months.
I'd group by the account, get the maximum date for each and then filter them using a having clause:
SELECT cellular_account_id
FROM invoices
GROUP BY cellular_account_id
HAVING MAX(billing_end_date) < DATE_SUB(CURRENT_DATE, INTERVAL 3 MONTH)
For my stystem I want to know how many times a visitor came to my shop. I got wifi sensors and they get alot of addresses and I want to know how many times the visitors came in a month
This is the database I use (time is in unix time and get fixed with FROM_UnixTime(sensordata1.time)
So what I want to get is a the address with the number of visits last month.(per day not per address so if he came 5times a day count it as 1)
You want to see March 2017. So restrict your results to March 2017 in the WHERE clause. You want one result row per visitor (address). So GROUP BY address. You want to count each day just once. So COUNT DISTINCT days.
select
address,
count(distinct from_unixtime(sensordata1.time, '%Y-%m-%d'))
from sensordata1
where from_unixtime(sensordata1.time, '%Y-%m') = '2017-03'
group by address;
If you want this more flexible, i.e. always the last month when executing the query instead of 2017-03 fixed, then find today, subtract a month, and take the month got thus.
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)
What is the best way to think about the Group By function in MySQL?
I am writing a MySQL query to pull data through an ODBC connection in a pivot table in Excel so that users can easily access the data.
For example, I have:
Select
statistic_date,
week(statistic_date,4),
year(statistic_date),
Emp_ID,
count(distict Emp_ID),
Site
Cost_Center
I'm trying to count the number of unique employees we have by site by week. The problem I'm running into is around year end, the calendar years don't always match up so it is important to have them by date so that I can manually filter down to the correct dates using a pivot table (2013/2014 had a week were we had to add week 53 + week 1).
I'm experimenting by using different group by statements but I'm not sure how the order matters and what changes when I switch them around.
i.e.
Group by week(statistic_date,4), Site, Cost_Center, Emp_ID
vs
Group by Site, Cost_Center, week(statistic_date,4), Emp_ID
Other things to note:
-Employees can work any number of days. Some are working 4 x 10's, others 5 x 8's with possibly a 6th day if they sign up for OT. If I sum the counts by week, I get anywhere between 3-7 per Emp_ID. I'm hoping to get 1 for the week.
-There are different pay code per employee so the distinct count helps when we are looking by day (VTO = Voluntary Time Off, OT = Over Time, LOA = Leave of Absence, etc). The distinct count will show me 1, where often times I will have 2-3 for the same emp in the same day (hits 40 hours and starts accruing OT then takes VTO or uses personal time in the same day).
I'm starting with a query I wrote to understand our paid hours by week. I'm trying to adapt it for this application. Actual code is below:
SELECT
dkh.STATISTIC_DATE AS 'Date'
,week(dkh.STATISTIC_DATE,4) as 'Week'
,month(dkh.STATISTIC_DATE) as 'Month'
,year(dkh.STATISTIC_DATE) as 'Year'
,dkh.SITE AS 'Site ID Short'
,aep.LOC_DESCR as 'Site Name'
,dkh.EMPLOYEE_ID AS 'Employee ID'
,count(distinct dkh.EMPLOYEE_ID) AS 'Distinct Employee ID'
,aep.NAME AS 'Employee Name'
,aep.BUSINESS_TITLE AS 'Business_Ttile'
,aep.SPRVSR_NAME AS 'Manager'
,SUBSTR(aep.DEPTID,1,4) AS 'Cost_Center'
,dkh.PAY_CODE
,dkh.PAY_CODE_SHORT
,dkh.HOURS
FROM metrics.DAT_KRONOS_HOURS dkh
JOIN metrics.EMPLOYEES_PUBLIC aep
ON aep.SNAPSHOT_DATE = SUBDATE(dkh.STATISTIC_DATE, DAYOFWEEK(dkh.STATISTIC_DATE) + 1)
AND aep.EMPLID = dkh.EMPLOYEE_ID
WHERE dkh.STATISTIC_DATE BETWEEN adddate(now(), interval -1 year) AND DATE(now())
group by dkh.SITE, SUBSTR(aep.DEPTID,1,4), week(dkh.STATISTIC_DATE,4), dkh.STATISTIC_DATE, dkh.EMPLOYEE_ID
The order you use in group by doesn't matter. Each unique combination of the values gets a group of its own. Selecting columns you don't group by gives you somewhat arbitrary results; you'd probably want to use some aggregation function on them, such as SUM to get the group total.
Grouping by values you derive from other values that you already use in group by, like below, isn't very useful.
week(dkh.STATISTIC_DATE,4), dkh.STATISTIC_DATE
If two rows have different weeks, they'll also have different dates, right?
I have a table titled "Reports" in MySQL that has a column titled "Flow_Total" which has a running total value that goes up every day and never resets, what i need is a query that takes the values that are stored in the "Flow_Total" column and divide them by month and tells me how much the value goes up every month.
This is how i would like to see the data:
https://skydrive.live.com/redir?resid=BC22A6E2F92CE833!11843&authkey=!ACgipFLKDJTBlN8
The value for the month is written on the last day of that month.
A summary of what i want to do is subtract the monthly change from the Flow_Total and display it in a separate column titled Monthly Total.
Maybe not the most pleasing SQL to the eyes, but this should do what you're asking; it'll just self join the table with itself delayed 1 month and calculate the difference from that.
SELECT DATE_FORMAT(MAX(a.`DATE`), '%b-%y') `DATE`,
MAX(a.`FLOW_TOTAL`) `Flow Total`,
(MAX(a.`FLOW_TOTAL`) - MAX(b.`FLOW_TOTAL`)) `Monthly Total`
FROM Reports a
LEFT JOIN Reports b
ON YEAR(a.`DATE`) = YEAR(DATE_ADD(b.`DATE`, INTERVAL 1 MONTH)) AND
MONTH(a.`DATE`) = MONTH(DATE_ADD(b.`DATE`, INTERVAL 1 MONTH))
GROUP BY YEAR(a.`DATE`), MONTH(a.`DATE`)
ORDER BY a.`DATE` DESC;
An SQLfiddle for testing.