SSRS Sorting by Year group total - reporting-services

I have a tablix that has Customer as the row group and Month and Year as Column Groups. Sales amount is in the data area. I would like to sort the customers in descending order by the Year total sales.
I tried the following (psuedo code)
SELECT
Period (a CONCAT of YEAR(date) and MONTH(Date),
SUM(Amount),
Company
FROM [tables]
Group by Period and Company
ORDER BY Sum(Amount) Desc
I did it this way thinking that if I sorted in the query it would come through in the order I want, but obviously it's showing the customer with the highest single month sales first, not the highest year.
Thinking more about it, if I want the report to be able to span multiple years, then I have to figure out which Year to total on, but I'd be happy to restrict the report to a single Year (identified by a parameter).
When I try to sort the tablix or customer group on Sum(Fields!Amount.value, "xYear") I get the error that aggregates can include groups.

I switched from Tablix to Matrix and now sorting the Customer Group by SUM(Fields!Amount.Value) works.... kind of.
It sorts by the grand total as opposed to a given year, but I can live with that for now. Maybe I'll add a parameter that defaults to the current year and try to figure out how to use that to enforce the sort. I'm thinking I may have to get the total YTD sales by customer in a separate dataset (that doesn't display in the report).

You could do it two ways.. (not tested... it's midnight here...) assuming you have a parameter to select the sort year and the Period is a date - adjust to suit...
You could sort by an expression something like
=SUM(
IIF(
YEAR(Fields!Period.Value) = Parameters!pSortYear.Value,
Fields!Amount.Value,
0),
"myDataSetName")
NOte The dataset name must match your dataset name exactly (case sensitive) and be enclosed in double quotes.
Or.. what I normally do is do it in SQL
SELECT Period, Company, SUM(Amount) AS Amount
INTO #data
FROM myTable
GROUP BY Period, Company
SELECT d.*, s.SortOrder
FROM #data d
JOIN (
SELECT Company, ROW_NUMBER() OVER(ORDER BY Amount DESC) as SortOrder
FROM #data
WHERE Period = #pSortYear
) s on d.Company = s.Company
Then in your report you can simply sort by SortOrder
This is done off he top of my head so there could be some basic errors but hopefully close enough for you to follow.

Related

how to get a count of orders for a given list of members and given intervals (equal to given_date +30day)

I wonder if anybody could give me an ideea on this query.
I have a list of memberID's and for each member I have a given set date (it represents a survey date)
Is there an easy SQL query to get a count of orders created in the interval: given_date and +30 day?... basically have the members placed an order in the following 30 days after the survey.
I am getting this list on a monthly basis.
In my database there is a 'members m' table and an 'orders o' table; the 'orders' table has a 'o.created' as date field.
I can easily search on a individual member level, but the member list can be large, several hundreds of distinct members & given_dates.
You can use GROUP BY with COUNT, e.g.:
SELECT id, COUNT(*)
FROM members
WHERE given_date BETWEEN '2017-10-12' AND DATE_ADD('2017-10-12', INTERVAL 30 DAY)
GROUP BY id;

GROUP BY in sql to get monthly breakdown of data

Say I have a data that describes different items sold and when they were sold. I want to breakdown this data and count different items sold on monthly basis. So here is what I have so far:
SELECT
ItemDescription
,OrderReceivedData
,COUNT(*) AS ItemCount
INTO 'C:\Users\whatever.csv'
FROM 'C:\user\inputFileHere.csv'
GROUP BY ItemDescription, OrderReceivedDate
HAVING OrderReceivedDate LIKE '%2011%'
Now the thing is that my dates are in a bad format. So what the query above does is that it shows count for an item on 01JAN2011, 02JAN2011, ... , 10FEB2011, ...and so on. But what I want is the count for JAN2011, FEB2011, MAR2011... and so on. So basically I dont wanna GROUP BY OrderReceivedData but I want to Group by these specific 7 characters in OrderReceivedDate so I can ignore the dates. I hope it makes sense. So how do I do this?
The simple approach, although a bit of a hack, is that you need to parse out the date characters, then group by that. For simplicity, you can reference the column by number. If you think this will change, repeat the parsing logic in your GROUP BY clause. This assumes the field contains two leading characters:
SELECT
ItemDescription
,RIGHT(OrderReceivedData, LEN(OrderReceivedData) - 2) AS MonthOrderReceivedData
,COUNT(*) AS ItemCount
INTO 'C:\Users\whatever.csv'
FROM 'C:\user\inputFileHere.csv'
GROUP BY ItemDescription, 2
HAVING OrderReceivedDate LIKE '%2011%'
I did not test this code, but should get you on the right track.
You first need to make use Log Parser undestands your OrderReceivedDate as a timestamp, and then you format it back as year-month and group by it:
SELECT
ItemDescription,
Month,
COUNT(*) AS TOTAL
USING
TO_STRING(TO_TIMESTAMP(OrderReceivedDate,'ddMMMyyyy'), 'yyyy-MM') as Month
INTO
'C:\Users\whatever.csv'
FROM
'C:\user\inputFileHere.csv'
WHERE
OrderReceivedDate LIKE '%2011%'
GROUP BY
ItemDescription,
Month
SELECT
ItemDescription
,SUBSTR(OrderReceivedDate,2,7) AS OrderReceivedDateUpdated
,COUNT(*) AS ItemCount
INTO 'C:\Users\whatever.csv'
FROM 'C:\user\inputFileHere.csv'
GROUP BY ItemDescription, OrderReceivedDateUpdated
HAVING OrderReceivedDate LIKE '%2011%'

MySQL Group By Order and Count(Distinct)

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?

Filter weekly from daily data and pick first occurence of the week

Assume you have a table with a stock time series on a daily basis.
Now you need to filter one data point per week, because you need weekly data for some analysis. You don't to have weekly averages, since this would leave much of the variation out.
This would be my initial approach, but it's not clear which of the data points falling in a given week is selected.
SELECT date, price from stock_series
GROUP BY WEEK(date)
1 How do I make sure it's always the first data point existing for a given week that gets picked?
EDIT:
2 If the above query stayed the way it is - which data point gets chosen every week? What's the MySQL logic in this case? Or is it just unpredictible?
If you want to have a better control over it, you could try using a subquery :
SELECT date,price
FROM stock_series
WHERE date IN
(
SELECT MIN(inner.date)
FROM stock_series inner
GROUP BY WEEK(inner.date)
) GROUP BY date
I've added GROUP BY date in the main query because you probably have more than one entry per day, otherwise it could be ommited.
EDIT:
or try joining with it:
SELECT date,price
FROM stock_series
JOIN
(
SELECT MIN(date) AS innerdate
FROM stock_series
GROUP BY WEEK(date)
) inner ON date=innerdate;
You can order by date ascending, which should give you just the first result of the WEEK() group.
SELECT date,price from stock_series
GROUP BY WEEK(date)
ORDER BY date

Query by month from date field

I have a set of Access d/b's grouped already by year. within a given year, I have a field caleld REPORTDATE which is a standard mm/dd/yyyy field. However, I need to produce queries that return data by the month. For example, I just want to see records for Jan, recs for Feb, Recs for March, etc., so that I can sum them and work wwith thm.
Do I use an expression in the query design view Criteria field?
Thanks in advance.
I just want to see records for Jan, recs for Feb, Recs for March, etc., so that I can sum them and work wwith thm.
You can do all of that in one sql statement:
select month(reportdate), sum( the column you wish to sum )
from tablename
group by month(reportdate);
BUT WAIT THERE'S MORE!
Further say that there are several salepersons selling stuff, and you wish to show each salesperson's sales by month
select month(reportdate), salesperson, sum( the column you wish to sum )
from tablename
group by month(reportdate), salesperson;
That shows the sum per month per salesperson.
You know the Germans always make good stuff!
What it you wanted to see the same sums, but rtaher than comparing salespeople against each other in each month, you wanted to compare, for each salesperson, how they did from one month to another?
Just reverse the order of the group by:
select month(reportdate), saleperson, sum( the column you wish to sum )
from tablename
group by salesperson, month(reportdate);
Tacos, Fettuccini, Linguini, Martini, Bikini, you're gonna love my nuts!
The power of SQL! As seen on TV! Order now!
"select month(reportdate), sum( the column you wish to sum )from tablenamegroup by month(reportdate);" THIS IS VERY HELPFUL, THANK YOU. AND YOU ARE HILARIOUS. HOWEVER, can you clarify for me where the heck this code goes?! In the expresison Builder or what? Thank you SO much. – rick (19 mins ago)
In Access, I think from the graphical Query Builder thing's menu, select edit|SQL, and just type. And never go back to graphical!
You're a hard-charging forward-thinking entrepreneurially-minded man on the move! This is not your father's Oldsmobile! You wouldn't use an on-screen keyboard to type a document, dragging and dropping letters on the page, would you?! So why do that to build a SQL Query? Get into SQL! AS SEEN ON TV! All the cool kids and hep cats are doin' it! Order NOW!
You can use format, for example:
Format([REPORTDATE],"mmm yy")
Or Month:
SELECT * FROM Table WHERE Month([REPORTDATE]) = 10
An outline of query that may suit, paste this into the SQL view of
the query design window, changing table to the name of your table:
SELECT Format([REPORTDATE],"yyyy mm"), Count([ReportDate])
FROM Table
GROUP BY Format([REPORTDATE],"yyyy mm")
I wouldn't do this in the report's recordsource. I'd make the recordsource a regular SELECT statement and use the report's sorting/grouping. If you group on a date field (one that is really date type), you get the choice to GROUP ON:
Each Value (default)
Year
Qtr
Month
Week
Day
Hour
Minute
I think this is faster than a GROUP BY on a function, but someone who was interested should actually try it.
Certainly if your SELECT with GROUP BY has no WHERE clause, it's going to be a lot more efficient if you run the report with filtered values.