SQL Over partition by - sql

I basically have a case statement that displays the sum of profit and a month to date total for each person. My idea is i want to display a daily figure of that person as well as their whole month total altogether.
My issue is when i limit results to just yesterday (supposed to be a daily figure) this then effects the calculation of the month value (just calculates the sum for that day rather than the whole month).
This is because the total month values are all out of the scope of the query. Is there anyway to calculate the whole month value for each person correctly without having the limits of where effecting the result.
e.g.
The result:
08/09/17: 25
09/09/17: 25
10/09/17: 25
11/09/17: 25 <<<< but only display one day and month total
Overall Month total: 100
Can this also includes nulls too? I think im almost looking at a dynamically stored month to date value that isn't effected by where clauses.
SELECT SUM(Figure) AS 'Daily Figure',
CASE WHEN
MONTH([DATE]) = MONTH(getdate()) AND
YEAR([DATE]) = YEAR(getdate())
THEN
SUM(Figure)
OVER (PARTITION BY [Name],
MONTH([DATE]))
ELSE 0 END
as [Month To Date Total]
WHERE
dateadd(day,datediff(day,1,GETDATE()),0)

If you want month-to-date and the current amount, then use conditional aggregation:
SELECT NAME,
SUM(CASE WHEN DAY(DATE) = DAY(GETDATE()) - 1 THEN Figure ELSE 0 END) AS DailyFigure,
SUM(Figure) as MonthToDate
WHERE MONTH([DATE]) = MONTH(getdate()) AND
YEAR([DATE]) = YEAR(getdate())
GROUP BY NAME;
This works on all but the first day of the month.

Related

SQL Server / SSRS: Calculating monthly average based on grouping and historical values

I need to calculate an average based on historical data for a graph in SSRS:
Current Month
Previous Month
2 Months ago
6 Months ago
This query returns the average for each month:
SELECT
avg_val1, month, year
FROM
(SELECT
(sum_val1 / count) as avg_val1, month, year
FROM
(SELECT
SUM(val1) AS sum_val1, SUM(count) AS count, month, year
FROM
(SELECT
COUNT(val1) AS count, SUM(val1) AS val1,
MONTH([SnapshotDate]) AS month,
YEAR([SnapshotDate]) AS year
FROM
[DC].[dbo].[KPI_Values]
WHERE
[SnapshotKey] = 'Some text here'
AND No = '001'
AND Channel = '999'
GROUP BY
[SnapshotDate]) AS sub3
GROUP BY
month, year, count) AS sub2
GROUP BY sum_val1, count, month, year) AS sub1
ORDER BY
year, month ASC
When I add the following WHERE clause I get the average for March (2 months ago):
WHERE month = MONTH(GETDATE())-2
AND year = YEAR(GETDATE())
Now the problem is when I want to retrieve data from 6 months ago; MONTH(GETDATE()) - 6 will output -1 instead of 12. I also have an issue with the fact that the year changes to 2016 and I am a bit unsure of how to implement the logic in my query.
I think I might be going about this wrong... Any suggestions?
Subtract the months from the date using the DATEADD function before you do your comparison. Ex:
WHERE SnapshotDate BETWEEN DATEADD(month, -6, GETDATE()) AND GETDATE()
MONTH(GETDATE()) returns an int so you can go to 0 or negative values. you need a user scalar function managing this, adding 12 when <= 0

SQL Query Average by Day of Week

I am trying to devise a query which will tell me the average number of procedures done on a given weekday as well as the total number of procedures on that week day for the entire time frame. The query I've developed looks like it works, but the values are not adding up correctly.
SELECT [Day], COUNT(*) AS "Week Day Count", AVG(Totals) AS [Avg]
FROM
(
SELECT
w = DATEDIFF(WEEK, 0, CompleteDate),
[Day] = DATENAME(WEEKDAY, CompleteDate),
Totals = COUNT(*)
FROM dbo.[order]
WHERE CompleteDate Between '2015-01-01' AND '2016-04-22'
AND PlacerFld2 IN ('CT','SAMR')
AND OrderStatusID = '2'
GROUP BY
DATEDIFF(WEEK, 0, CompleteDate),
DATENAME(WEEKDAY, CompleteDate),
DATEPART(WEEKDAY, CompleteDate)
) AS q
GROUP BY [Day]
ORDER BY [Day];
I feel like the Average results are correct, however, the "Week Day Count" does not come up nearly as high as I thought it should be and perhaps it's just the way I am computing it.
When I add up the values in the Week Day Count it comes up to be about 365, but when I do the query below, I get about 1750:
SELECT COUNT(*) AS "Total 2015-2016"
FROM [order]
WHERE CompleteDate Between '2015-01-01' AND '2016-04-22'
AND PlacerFld2 IN ('CT','SAMR')
AND OrderStatusID = '2'
I suspect that you actually want the sum of the total:
SUM(Totals) AS "Week Day Count"
Your query is (I think) counting the number of days in the data for each weekday.

combining dates when doing a sum query

I would like to sum values over time. The difficulty that i am having with this is if there is a way to assign a date to the end value.
To clarify, here is my example table.
Object Observation Date
1 215 10/1/2015
2 125 10/1/2015
1 225 10/4/2015
2 150 10/4/2015
1 250 10/8/2015
The idea is to sum the observation by Object and Date. This is easy, the hard part is something I'm not sure how i would do. Currently I sum by month using this query
SELECT Object, Sum(Observation) AS [Total], Month([Date]) AS [Month],
FROM Records
GROUP BY Month([Date]), Object;
This gives my the total for the month. Ideally what I would like to do though is to make it so that rather than getting a numeric month, mm, I get a date mm/dd/yyyy. So the Date post sum would show up as 10/01/2015.
So that output would look something like this:
Object Total Date
1 690 10/1/2015
2 275 10/1/2015
I have build out a query that uses a calendar to select a start and end date for pulling multiple months at a time that I might want to compare.
SELECT Object, Date, Total
FROM Table1
WHERE [Month] Between Month(Forms![Main Form]![Start Date]) And Month(Forms![Main Form]![End Date])
GROUP BY Object, Month, Total;
My current method doesn't allow for me to roll over into the next calendar year. The hope is that this would fix my issue with the roll over issue. Is this possible to assign the first of the month to the date after the month is summed?
That could be:
SELECT
Object,
DateSerial(Year([Date]), Month([Date]), 1) As YearMonth,
Sum(Observation) AS [Total]
FROM
Table1
WHERE
[Date]
Between Forms![Main Form]![Start Date]
And Forms![Main Form]![End Date]
GROUP BY
Object,
DateSerial(Year([Date]), Month([Date]), 1)
You can use DateSerial() to determine the first day of the month.
SELECT Object, Sum(Observation) AS [Total], DateSerial(Year(Date()), Month(Date()),1) AS [Month],
FROM Records
GROUP BY DateSerial(Year(Date()), Month(Date()),1), Object;

Combining daily averages for different time periods in a single query

I have a table with hourly entries for multiple products dating back to 2 years. I am trying to write a query which would look something like this:
PRODUCT, TODAY'S AVERAGE, LAST MONTHS DAILY AVERAGE, YEAR TO DATE DAILY AVERAGE
I am able to achieve this by writing separate queries for each of the averages and then joining them on the PRODUCT NAME. However, I want to be able to do the same, by writing one single query.
Is their a standard algorithm/method that I can apply?
This is an aggregation query. However, it gets variables for each of the time periods you want, and sums by day to do the final calculations.
select product,
sum(DailySum*IsToday) as Today,
sum(1.0*DailySum*IslastMonth) / sum(IslastMonth)
sum(1.0*DailySum*IsYTD) / sum(IsYTD)
from (select product, cast(dt as date) as thedate, sum(val) as DailySum
(case when cast(dt as date) = cast(getdate() as date) then 1 else 0 end) as IsToday,
(case when year(dt) = year(dateadd(month, -1, getdate()) and month(dt) = month(dateadd(month, -1, getdate())
then 1 else 0
end) as IslastMonth,
(case when year(dt) = year(getdate()) tehn 1 else 0
end) as IsYTD
from t
group by product, cast(dt as date)
) t
) t

Fiscal Year To-Date in Where Clause (T-SQL)

Company's Fiscal Year: July 1 - June 30
I have a query where I am trying to capture aggregate # of units and $ revenue by product and cost center for the fiscal year-to-date. It will run on the 1st of the month and look through the last day of the previous month. Fiscal year does not appear in the report - it is criteria.
Mix of pseudocode and SQL:
Where
If datepart(mm,getdate()) - 1 < 7
THEN
transaction_post_date BETWEEN 7/1/ previous year AND dateadd(day,-(day(getdate()),getdate())
Else
transaction_post_date BETWEEN 7/1/current year AND dateadd(day,-(day(getdate()),getdate())
Am I on the write track? How do I write the SQL for a specific date on a year that depends on SQL - 7/1/current year?
I am weak using variables and do not even know if I have access to create them on the SQL Server DB, which is rather locked down. Definitely can't create a function. (I'm a business analyst.)
UPDATE, Fiscal year goes forward, so July 1, 2010, is Fiscal Year 2011.
I think this works:
Year(dateadd(month,6,htx.tx_post_date)) = Year(DateAdd(Month, 5, GetDate()))
Feeback?
And now I've been asked to add Fiscal Year-To-Date fields for quantity and revenue to the following query which gave me totals for
Select
inv.ITEM_CODE
, inventory.ITEM_NAME
, cc.COST_CENTER_CODE
, tx.REV_CODE_ID
, tx.PRICE
, tx.ITEM_SALE_ID
, sum(tx.quantity)
, sum(tx.amount)
from
transactions tx
inner join inventory inv on inv.item_id = tx.item_id
left outer join cost_center cc on cc.cost_center_id = tx.cost_center_id
where
DATEPART(mm, tx.tx_date) = DATEPART(mm,dateadd(m,-1,getdate()))
and DATEPART(yyyy, tx.tx_date) = DATEPART(yyyy,dateadd(m,-1,getdate()))
group by
inv.ITEM_CODE
, inventory.ITEM_NAME
, cc.COST_CENTER_CODE
, tx.REV_CODE_ID
, tx.PRICE
, tx.ITEM_SALE_ID
I need to add the fiscal year-to-date quantity and and amount columns to this report. Would a correlated subquery by the way to go? Would the joins be tricky? I've never used a subquery with an aggregation/grouping query.
Thanks for all the previous help.
Here is how I would do it if I needed to group by Fiscal Year:
Group by Year(DateAdd(Month, -6, TransactionDate))
May be not exactly it, but you get the idea.
I would add a calculated column to your table called FiscalYear (with the proper calculation) and select based on that column
I believe the easiest way is to do this in two steps. Use the WHERE Clause to filter your YTD and then a GROUP BY to group by FY. Since your FY begins in July(7) then increment the FY if the month is greater than June(6).
WHERE CLAUSE:
WHERE
DATEDIFF(DAY, transaction_post_date, Cast(Month(GetDate()) as varchar) +
'/' + Cast(Day(GetDate()) as varchar) + '/' + CAST(Case WHEN
MONTH(transaction_post_date) > 6 then YEAR(transaction_post_date) + 1 else
Year(transaction_post_date) end as varchar)) >=0
GROUP BY CLAUSE:
GROUP BY CASE WHEN MONTH(transaction_post_date) > 6 then
Year(transaction_post_date) + 1 else YEAR(transaction_post_date) end