SQL Server Adding summing values based on the month - sql

I have a table that has the following 2 columns:
Date and Price
I want to sum the prices based on the same month of the same year. This is what I have:
2012-07-27 00:00:00.000 0
2012-07-27 00:00:00.000 15000
2012-08-27 00:00:00.000 0
2012-08-27 00:00:00.000 12000
2012-09-28 00:00:00.000 1000
2012-09-28 00:00:00.000 9000
2012-10-26 00:00:00.000 0
I want the following:
2012-07-27 00:00:00.000 15000
2012-08-27 00:00:00.000 12000
2012-09-28 00:00:00.000 10000
2012-10-26 00:00:00.000 0
Thank you.

You could get your desired result given your sample data and output with:
SELECT DATE, SUM(Price)
FROM YourTable
GROUP BY DATE
ORDER BY DATE
If you had multiple dates in a month and wanted to return each distinct date but still show the monthly sum for each record you could use:
SELECT DATE, SUM(SUM(Price)) OVER (PARTITION BY YEAR(Date),MONTH(Date))
FROM YourTable
GROUP BY DATE
ORDER BY DATE

You'll want to use the date functions provided in a group by statement, something like:
select sum(price)
,cast(datepart(month, date_column) as varchar) + '-' + cast(datepart(year, date_column) as varchar) as year_month
from your_table
group by datepart(year, date_column), datepart(month, date_column)
Make sure to put the datepart(year, date_column) first, so that you don't get a sum of all prices from every January from all years, but instead get a sum of all prices from January 2012.
The result set for this query will look a little different than your example - you'd get:
07-2012 15000
08-2012 12000
09-2012 10000
10-2012 0
If you want to get the exact result set you provided, you can change the first column of the select statement:
select sum(price)
,date_column
from your_table
group by datepart(year, date_column), datepart(month, date_column)
The downside to this is that if you have multiple days from the same month/year, say 8/12/2013 and 8/13/2013, it will be hard to predict which of the two days you'll get in the final result set.

I agree with prekolna's answer that it is probably what you really need. However, to produce what you have in your question, you only need to group by the date since the dates are all the same in the month and since you have the dates displayed in the return:
SELECT
[Date],
SUM(Price) Price
FROM
a_table
GROUP BY
[Date];
The above assumes you only have one unique date entry per month and that you want the full date returned. These are admittedly bad assumptions. I would change prekolna's example slightly to ensure the date column can sort properly and to match it in the group by:
SELECT
CAST(DATEPART(YEAR, [Date]) AS varchar(4)) + '-' + RIGHT('0' + CAST(DATEPART(MONTH, [Date]) AS varchar(2)), 2) YearMonth,
SUM(Price) Price
FROM
a_table
GROUP BY
CAST(DATEPART(YEAR, [Date]) AS varchar(4)) + '-' + RIGHT('0' + CAST(DATEPART(MONTH, [Date]) AS varchar(2)), 2);
Or, you can do something else to return a full date like a MIN:
SELECT
MIN([Date]) [Date],
SUM(Price) Price
FROM
a_table
GROUP BY
CAST(DATEPART(YEAR, [Date]) AS varchar(4)),
CAST(DATEPART(MONTH, [Date]) AS varchar(2));

Related

How to get quarterly data from monthly in SQL Server

I have table where I am having monthly data like below.
Here my AvgSpeedOfAnswer column is calculated like this:
avg(SpeedOfAnswer)
Table:
Date
AvgSpeedOfAnswerMonth
7/1/2022
20.8
8/1/2022
22.6
9/1/2022
24.9
Now my requirement is I need to create a query where I can get quarterly data from above monthly table data.
I wrote a query like this:
SELECT
'Quarterly' AS TrendType,
DATEADD(Q, DATEDIFF(Q, 0, TrendStartdate), 0) AS TrendStartdate,
SUM(AvgSpeedOfAnswer)
FROM
Month_Stats
GROUP BY
DATEADD(Q, DATEDIFF(Q, 0, TrendStartdate), 0)
ORDER BY
DATEADD(Q, DATEDIFF(Q, 0, TrendStartdate), 0)
I am not sure what should I need to take for AvgSpeedOfAnswer.
Is it SUM(AvgSpeedOfAnswerMonth) or AVG(AvgSpeedOfAnswerMonth) or AVG(SUM(AvgSpeedOfAnswerMonth))?
Could anyone please suggest?
As others mentioned.
You need to use DATEPART
SELECT
'Quarterly' AS TrendType,
DATEFROMPARTS(YEAR(Date), ((DATEPART(Q, Date) - 1) * 3) + 1, 1) AS TrendStartdate,
AVG(AvgSpeedOfAnswerMonth) AS AvgSpeedOfAnswerQuarter
FROM
Month_Stats
GROUP BY
YEAR(Date),
DATEPART(Q, Date)
ORDER BY
YEAR(Date),
DATEPART(Q, Date)
you can use DATEPART and QUARTER
CREATE TABLE tabl11
([Date] datetime, [AvgSpeedOfAnswerMonth] DECIMAL(10,1))
;
INSERT INTO tabl11
([Date], [AvgSpeedOfAnswerMonth])
VALUES
('2022-07-01 02:00:00', 20.8),
('2022-08-01 02:00:00', 22.6),
('2022-09-01 02:00:00', 24.9)
;
3 rows affected
SELECT YEAR([Date]), DATEPART(QUARTER, [Date]), SUM([AvgSpeedOfAnswerMonth]) sum_quarterly FROM tabl11
GROUP BY YEAR([Date]),DATEPART(QUARTER, [Date])
(No column name)
(No column name)
sum_quarterly
2022
3
68.3
fiddle
I think you need avg (AvgSpeedOfAnswerMonth) to get the quarterly average speed over the quarter. Sum(AvgSpeedOfAnswerMonth) and avg(sum(AvgSpeedOfAnswerMonth) give the same value, which is the sum of the quarterly values.
Use the DATEPART function with parameter QUARTER, like
select 'Quarterly' as Quarterly, date as date from yourTable
group by DATEPART(quarter, date)
order by DATEPART(quarter, date)

last date of Financial year (I.e 2017-03-31)

Hi please let me know how to extract the last day of Financial year in sql server.my financial year start from 2016-04-01 to 2017-03-31
Closest you can use is End Of Month for that you need to provide one date to that month as below:
select eomonth('2017-03-01')
To get the last day of the financial year for any date, you need to find the last of march if before march, or the last of march next year if after march:
declare #yourdate datetime = getdate();
select case when month(#yourdate) < 4 then CONVERT(datetime,cast(YEAR(#yourdate) as char(4)) + '-03-31' ,120)
else CONVERT(datetime,cast(YEAR(#yourdate) + 1 as char(4)) + '-03-31' ,120)
end as financial_year_end
Edit:
If you want last date derived based on from_date, then use something like this
Rextester Demo
select
case when datepart(mm,from_date) <=3 then
cast(concat(year(from_date),'-03-31') as datetime)
else
dateadd(year,1,cast(concat(year(from_date),'-03-31') as datetime))
end as last_date_fin
from
(select '2017-04-30' as from_date union all
select '2017-01-13') t;
This way from_date between Jan - Mar will give same year's 31st march. Else it will give next year's 31st March.
Previous answer:
http://rextester.com/AXVM26769
If you want to get last day of march for same year as passed, then use
select cast(concat(given_year,'-03-31') as datetime)
from
(select '2017' as given_year) t
If you want to pass 2016 and then get 2017-03-31 then use. You can change the year in derived table and change the output based on that.
select dateadd(year,1,cast(concat(given_year,'-03-31') as datetime))
from
(select '2016' as given_year) t;
This Code will work to find the last date of Financial Year.
For Previous Year case matches and 'THEN' part will Execute and for current year 'ELSE'
part will execute.
select CASE WHEN (MONTH(GETDATE())) <= 3
THEN convert(varchar(4), YEAR(GETDATE())-1) + '-' + '03-31'
ELSE convert(varchar(4),YEAR(GETDATE()))+ '-' + '03-31'
end
> LastDayOfYearFY] =
> eomonth( dateadd(month, 5,
> dateadd(year, datepart(year, (dateadd(month, 6, [date])) ) -1900, 0)))
Idea extension taken from return-first-day-of-financial-year
You can select all the dates order them descendant and take the first one.
SELECT date
FROM table
ORDER BY date desc
LIMIT 1;

Rounding dates to first day of the month

I am using SQL Server 2014 and I am working with a column from one of my tables, which list arrival dates.
It is in the following format:
ArrivalDate
2015-10-17 00:00:00.000
2015-12-03 00:00:00.000
I am writing a query that would pull data from the above table, including the ArrivalDate column. However, I will need to convert the dates so that they become the first day of their respective months.
In other words, my query should output the above example as follows:
2015-10-01 00:00:00.000
2015-12-01 00:00:00.000
I need this so that I can create a relationship with my Date Table in my PowerPivot model.
I've tried this syntax but it is not meeting my requirements:
CONVERT(CHAR(4),[ArrivalDate], 100) + CONVERT(CHAR(4), [ArrivalDate], 120) AS [MTH2]
If, for example, it is 15th of given month then you subtract 14 and cast the result to date:
SELECT ArrivalDate
, CAST(DATEADD(DAY, -DATEPART(DAY, ArrivalDate) + 1, ArrivalDate) AS DATE) AS FirstDay
FROM (VALUES
(CURRENT_TIMESTAMP)
) AS t(ArrivalDate)
ArrivalDate | FirstDay
2019-05-15 09:35:12.050 | 2019-05-01
But my favorite is EOMONTH which requires SQL Server 2012:
SELECT ArrivalDate
, DATEADD(DAY, 1, EOMONTH(ArrivalDate, -1)) AS FirstDay
FROM (VALUES
(CURRENT_TIMESTAMP)
) AS t(ArrivalDate)
ArrivalDate | FirstDay
2019-05-15 09:35:52.657 | 2019-05-01
Use FORMAT to format your date.
DECLARE #date DATETIME = '2015-10-17 00:00:00.000'
SELECT FORMAT(#date, 'yyyy-MM-01 HH:mm:ss.fff')
Or if you don't want time part:
SELECT FORMAT(#date, 'yyyy-MM-01 00:00:00.000')
LiveDemo
Beginning with SQL Server 2012, you can also use DATEFROMPARTS:
SELECT DATEFROMPARTS(YEAR(ArrivalDate), MONTH(ArrivalDate), 1)
FROM my_table
Round date to first of the month:
DATEADD(MONTH, DATEDIFF(MONTH, 0, DateColumn), 0)
Or just simply use the ROUND function -
SELECT ROUND (TO_DATE ('27-OCT-00'),'YEAR')
"New Year" FROM DUAL;
New Year
01-JAN-01

How to group daily data on weekly basis using sql

I am trying to group the number of hours that employees worked for the last 4 weeks but I want to group them on a weekly basis. For example:
WEEK HOURS
Feb 24 to March 2 55
March 3 to March 9 40
March 10 to March 16 48
March 17 to March 23 37
This is what I have so far, please help. thanks
SET DATEFIRST 1
SELECT CAST(MIN( [DT]) AS VARCHAR(20))+' TO '+CAST (MAX([DT]) AS VARCHAR(20)) AS DATE,
SUM(HOURS) AS NUM_HRS
FROM MyTable
GROUP BY DATEPART(WEEK,[DT])
HAVING COUNT(DISTINCT[DT])=7
Create a Calendar auxilliary table, with Year, Month, Week, Date columns (you can also add holidays and other interesting stuff to it, it has many potential uses) and populate it for the period of interest.
After that, it's as easy as this:
SELECT sum(hours), cast(min(date) as varchar), cast(max(date) as varchar)
FROM Calendar c
LEFT OUTER JOIN MyTable h on h.Date = c.date
GROUP BY year, week
ORDER BY year, week
SET DATEFIRST 1
SELECT DATEPART(WEEK,DT) AS WEEK,
SUM(HOURS) AS NUM_HRS
FROM MyTable
WHERE DT >= DATEADD(WEEK, -4, GetDate()),
GROUP BY DATEPART(WEEK,[DT])
Try something like
SELECT
DATEADD(DD,
CONVERT(INT, (DATEDIFF(DD, '1/1/1900', t.DT)/7)) * 7,
'1/1/1900') [WeekBeginDate],
DATEADD(DD,
(CONVERT(INT, (DATEDIFF(DD, '1/1/1900', t.DT)/7)) * 7) + 6,
'1/1/1900') [WeekEndDate],
SUM(HOURS) AS NUM_HRS
FROM MyTable t
GROUP BY CONVERT(INT, DATEDIFF(DD, '1/1/1900', t.DT)/7)
Though this is the brute force trick, I think in your case it will work.
EDIT : Modified the query a little bit, the error was caused because of the order in which DATEDIFF calculates the difference.
Also here is a SQL FIDDLE with a working example.
EDIT 2 : Updated the Fiddle with the Date Format. To customize the date format, this article would help.

sql server group by datetime cut-off point of 10:00am

I'm trying to write a Microsoft SQL Server 2005 query that counts a total value, grouped by date with a cut-off point of 10:00am ?
eg: Table Orders
DateReceived Total
01-01-2012 06:10:01 2
01-01-2012 08:10:01 2
01-01-2012 10:10:01 4
02-01-2012 08:00:07 4
02-01-2012 10:00:07 4
I'd like to count the daily total, using 10:00 am as the cut-off point, so any orders before 10:00am appear in the total for the day before, and after 10:00 am in the total for that day.
I'm hoping to see query results like:
DateReceived Total
31-12-2011 4
01-01-2012 8
02-01-2012 4
I know how to group by just the date in Microsoft SQL Server:
SELECT DISTINCT CONVERT(varchar, [DateReceived], 111) AS [dt_DateReceived],
SUM([Total]) AS perday
FROM [Orders]
GROUP BY CONVERT(varchar, [DateReceived], 111)
ORDER BY [DateReceived] DESC
However I am unsure how to add a cut off time of 10:00am using Microsoft SQL Server.
Using MySQL, I can achieve this by grouping on a subtracted interval, however am unsure how to translate this to SQL Server:
GROUP BY
DATE(DATE_SUB( DateReceived , INTERVAL 10 HOUR))
Could anyone advise?
Thank you,
Jack
See the translation:
SELECT
CONVERT(varchar, DATEADD(hour, -10, [DateReceived]), 111) AS [dt_DateReceived],
SUM([Total]) AS perday
FROM [Orders]
GROUP BY CONVERT(varchar, DATEADD(hour, -10, [DateReceived]), 111)
ORDER BY 1 DESC
Test script
Note that my local datetime format is yyyy-mm-dd
;WITH Orders AS (
SELECT * FROM (VALUES
(CAST('2012-01-01 06:10:01' AS DATETIME), 2)
, ('2012-01-01 08:10:01', 2)
, ('2012-01-01 10:10:01', 4)
, ('2012-01-02 08:00:07', 4)
, ('2012-01-02 10:00:07', 4)
) AS Orders (DateReceived, Total)
)
SELECT CONVERT(varchar, DATEADD(hour, -10, [DateReceived]), 111) AS [dt_DateReceived]
, SUM([Total]) AS perday
FROM [Orders]
GROUP BY
CONVERT(varchar, DATEADD(hour, -10, [DateReceived]), 111)
ORDER BY
1
The testscript can be executed here
PS: Distinction is not needed