I am so sorry if there is already an answer for this question, I just haven't been able to find it.
I am making a little chart to my home systems, which is a overview of my savings, I already have a chart showing how much is going in each months.
This is the SQL statement I have managed to get working so far
SELECT SUM(amount) AS total, DATE(dt) AS `date` FROM `savings` GROUP BY MONTH(`date`)
Which gives this result:
SQL result image
But this is not fully what I am doing to get, since this statement gives an amount for each month, what I need is one that add to the last amount, so that I can see the full amount of saving over months, if that makes sense?
It sounds like you want WITH ROLLUP:
SELECT SUM(amount) AS total, EXTRACT(YEAR_MONTH FROM dt) AS `yearmonth`
FROM `savings`
GROUP BY yearmonth WITH ROLLUP;
This does your grouping by year/month, plus adds one more row to the result set, with the total. The yearmonth column will be returned as NULL on that rollup row.
Related
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.
select
substr(insert_date, 1, 14),
device, count(1)
from
abc.xyztable
where
insert_date >= DATE_SUB(NOW(), INTERVAL 10 DAY)
group by
device, substr(insert_date, 1, 14) ;
and then I am trying to get average of the same rows count which I got above.
SELECT
date, device, AVG(count)
FROM
(SELECT
substr(insert_date, 1, 14) AS date,
device,
COUNT(1) AS count
FROM
abc.xyztable
WHERE
insert_date >= DATE_SUB(NOW(), INTERVAL 10 DAY)
GROUP BY
device, substr(insert_date, 1, 14)) a
GROUP BY
device, date;
AS I found both queries return the same results, I tried for last 10 days data.
My purpose is to get the average rows count for last 10 days which I get from the above 1st query.
I'm not entirely sure what you're asking, the "difference" between the two queries is that the first one is valid but the second does not appear to be, as per HoneyBadger's comment. They also seem to be trying to achieve two different goals.
However, I think what you are trying to do is produce a query based on the data from the first query, which returns the date, device, and an average of the count column. If so, I believe the following query would calculate this:
WITH
dataset AS (
select substr(insert_date,1,14) AS theDate, device, count(*) AS
theCount
from abc.xyztable
where insert_date >=DATE_SUB(NOW(), INTERVAL 10 DAY)
group by device,substr(insert_date,1,14)
)
SELECT theDate, device, (SELECT ROUND(AVG(CAST(theCount
AS FLOAT)), 2) FROM
dataset) AS Average
FROM dataset
GROUP BY theDate, device
I have referenced the accepted answers of this question to calculate the average: How to calculate average of a column and then include it in a select query in oracle?
And this question to tidy up the query: Formatting Clear and readable SQL queries
Without having a sample of your data, or any proper context, I can't see how this would be especially useful, so if it was not what you were looking for, please edit your question and clarify exactly what you need.
EDIT: Based on what extra information you have provided, I've made a tweak to my solution to increase the precision of the average column. It now calculates the average to two decimal places. You have stated that this returns the same result as your original query, but the two queries are not formulating the same thing. If the count column is consistently the same number with little variation, the AVG function will round this, which in turn could produce results which look the same, especially if you only compare a small sample, so I have amended my answer to demonstrate this. Again, we'd all be able to help you much easier if you would provide more information, such as a sample of your data.
If you want an average you need to change the last GROUP BY
to get an average per device
GROUP BY device;
to get an average per date
GROUP BY date;
or remove it completely to get an average for all rows in the sub-query
Update
Below is a full example for getting the average per device
SELECT device, avg(count)
FROM (SELECT substr(insert_date,1,14) as date, device, count(1) as count
FROM abc.xyztable
WHERE insert_date >=DATE_SUB(NOW(), INTERVAL 10 DAY)
GROUP BY device,substr(insert_date,1,14)) a
GROUP BY device;
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?
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
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.