Pivot 12 Months dynamically backwards from current month - sql

I have a table that looks like this:
CustName
Date
Hours
First
01/01/2021
12
Second
01/01/2021
10
Second
05/02/2021
1
Second
10/11/2021
14
I am trying to do a sum of hours per month per customer.
I figured out how to do this using a Pivot such as:
SELECT
CustName AS [Customer], ISNULL([January],0) AS [January], ISNULL([February],0) AS [February], ISNULL([March],0) AS [March]
FROM
(
SELECT
CustName,
DATENAME(MONTH, Date) AS [Month],
RegHrs
FROM TimeEntrySimpleList
) AS Src
PIVOT
(
SUM(Hours)
FOR [Month] IN ([January], [February], [March])
) AS Pvt
select* from TimeEntry
This works fine if I want to report say January - December in a static way, only ever showing the months I assign.
But what I want to do is have the last month column (March in my example), and show 12 months from the current backwards in the columns.
I'm guessing I would have to set the current month as a variable? And use it in the pivot .. but I'm not sure how / what to do. Use some sort of calc [month]*12 (reverse)?
Any tips would be appreciated!

Related

Remove Duplicates and show Total sales by year and month

i am trying to work with this query to produce a list of all 11 years and 12 months within the years with the sales data for each month. Any suggestions? this is my query so far.
SELECT
distinct(extract(year from date)) as year
, sum(sale_dollars) as year_sales
from `project-1-349215.Dataset.sales`
group by date
it just creates a long list of over 2000 results when i am expecting 132 max one for each month in the years.
You should change your group by statement if you have more results than you expected.
You can try:
group by YEAR(date), MONTH(date)
or
group by EXTRACT(YEAR_MONTH FROM date)
A Grouping function is for takes a subsection of the date in your case year and moth and collect all rows that fit, and sum it up,
So a sĀ“GROUp BY date makes no sense, what so ever as you don't want the sum of every day
So make this
SELECT
extract(year from date) as year
,extract(MONTH from date) as month
, sum(sale_dollars) as year_sales
from `project-1-349215.Dataset.sales`
group by 1,2
Or you can combine both year and month
SELECT
extract(YEAR_MONTH from date) as year
, sum(sale_dollars) as year_sales
from `project-1-349215.Dataset.sales`
group by 1

SQL Server - Cumulative Sum over Last 12 Months, but starting from the Last Month (SQL Server 18)

I need to run a cumulative sum of a value over the Last 12 Months. So far, my cumulative calculation are working, but starting from the Current Month.
I need the total of Last 12 Months, starting from the Last Month.
Currently, I'm using OVER clause on SQL, starting to running the cumulative total from the current row/month.
Please, refer below my code example:
SELECT *,
SUM(Amount) OVER (PARTITION BY ID ORDER BY Date_Month ROWS BETWEEN 11 PRECEDING AND CURRENT ROW) AS TwelveMoTtl
FROM (
SELECT DISTINCT
CAST(DATEADD(MONTH, DATEDIFF(MONTH, 0, TransactionDt), 0) AS DATE) AS Date_Month,
ID,
SUM(Amount) AS Amount
FROM MyTable
WHERE TransactionDt >= '2019-01-01'
GROUP BY
ID,
CAST(DATEADD(MONTH, DATEDIFF(MONTH, 0, TransactionDt), 0) AS DATE)
Here is my results (using only one ID to simplify the example):
As my example, the calculation are starting from the current row, and running over the last 12 months.
If we take the February row for example, I need the cumulative sum from Jan, 2020 to February, 2019.
Any suggestions how could I do it?
Thanks,
You seem to understand window functions pretty well. You just have to adjust the window frame:
SUM(Amount) OVER (PARTITION BY ID
ORDER BY Date_Month
ROWS BETWEEN 12 PRECEDING AND 1 PRECEDING
)
I forgot that I may have NULL rows in my table. So, the solution as to do a cumulative sum, even if there's missing dates. For example:
I need to running over the last 12 calendar months whether there are amount in those months or not.
Any ideas?
Thanks,
Rafael

SQL how to sum quantity monthly for report

I have table like this
PartID Quantity Date
12315 1 2017-01-24
51245 3 2017-01-26
12345 4 2017-02-20
12415 1 2017-02-25
..... .. ...........
I need for the report result like:
Monthly Quantity January: 4
Monthly Quantity February: 5
So in my report - every column should have the name of month and include all quantities (count) for this month. Any help would be appreciated.
I think you are looking for a query like:
select month(Date), sum(Quantity)
from table
group by month(Date)
In MS SQL :
You can use something like this:
DATENAME() function returns a specified part of a given date, as a string value.
To know more about DATENAME(), please visit https://www.w3schools.com/sql/func_sqlserver_datename.asp
CAST() function converts an expression from one data type to another data type.
To know more about CAST(), please visit https://www.w3schools.com/sql/func_sqlserver_cast.asp
SELECT
MONTH(Date) AS MonthNo,
'Monthly Quantity ' + DATENAME(MONTH, date) + ' : ' + CAST(SUM(Quantity) AS nvarchar(10)) AS Monthwise
FROM parttable
GROUP BY DATENAME(MONTH, date),
MONTH(Date)
ORDER BY MONTH(Date)
So the output will be
Two options you can have :
1) create another column and store name of month in it .
PartID Quantity Date. Month
12315 1 2017-01-24. January
51245 3 2017-01-26. January
12345 4 2017-02-20. February
12415 1 2017-02-25. February
And use below query to get the report as you needed :
Select sum(Quantity) as total_quantity, Month from table group by Month
2) by using inbuilt date and time functions of MySQL.
Select sum(Quantity) as total_quantity, Month(Date) as month from table group by Month(Date)
Which database are you using?
On SQL Server:
SELECT
DATENAME(month, Date) AS 'Month Name', SUM(Quantity)
FROM table
GROUP BY DATENAME(month, Date)

Modification todate dimension in SQL Server

I need a suggestion around one of the columns that I'm creating in the Date dimension in SQL Server, basically rolling weeks..
I have a table dimDate in my datawarehouse.
I want to create a column in the dimdate table which will have week number in any year and each week should have 7 days.
For eg: In year 2015 there are 53 weeks but the 53rd week has only 5 days (because the week starts on Sunday in SQL Server I guess).
I want to include 2 more days from 2016 (1st and 2nd Jan in 2016) to complete the 53rd week with 7 days and also the the 1st week in 2016 should start on 3rd of Jan 2016, so on and so forth.
If there are any suggestions that will be great to start with.
Assuming that you already have weeks populated (but not extended into the next year), and making some assumptions about columns names
This query finds the last week in a year (which would almost always always be 53 but don't count on it:) and the date that it ends on
SELECT YearNo, MAX(Week) As Week, MAX(DateKey) As DateKey
FROM dimDate
GROUP BY YearNo
This query finds all weeks that are shorter than 7 days, and how many extra days are required to make them 7 days.
SELECT
YearNo,
Week,
7-COUNT(DISTINCT DateKey) As ExtraDaysRequired
FROM dimDate
GROUP BY YearNo, Week
HAVING COUNT(DISTINCT DateKey) < 7
This might always be the last week of the year but lets not make assumptions.
Lets combine these to find all final weeks that have less than 7 days, as well as add the number of days required:
SELECT
Under7Days.YearNo, Under7Days.Week, Under7Days.ExtraDaysRequired,
FinalWeeks.DateKey StartDate,
DATEADD(d,Under7Days.ExtraDaysRequired,FinalWeeks.DateKey) EndDate
FROM
(
SELECT YearNo, MAX(Week) As Week, MAX(DateKey) As DateKey
FROM dimDate
GROUP BY YearNo
) As FinalWeeks
INNER JOIN
(
SELECT YearNo, Week, 7-COUNT(DISTINCT DateKey) As ExtraDaysRequired
FROM dimDate
GROUP BY YearNo, Week
HAVING COUNT(DISTINCT DateKey) < 7
) As Under7Days
ON FinalWeeks.Week = Under7Days.Week
AND FinalWeeks.YearNo = Under7Days.YearNo
So we have a query that identifies the start date and end date and week number that it needs to be updated to. So now we run an update:
UPDATE TGT
SET Week = SRC.Week
FROM dimDate TGT
INNER JOIN
(
SELECT
Under7Days.YearNo, Under7Days.Week, Under7Days.ExtraDaysRequired,
FinalWeeks.DateKey StartDate,
DATEADD(d,Under7Days.ExtraDaysRequired,FinalWeeks.DateKey) EndDate
FROM
(
SELECT YearNo, MAX(Week) As Week, MAX(DateKey) As DateKey
FROM dimDate
GROUP BY YearNo
) As FinalWeeks
INNER JOIN
(
SELECT YearNo, Week, 7-COUNT(DISTINCT DateKey) As ExtraDaysRequired
FROM dimDate
GROUP BY YearNo, Week
HAVING COUNT(DISTINCT DateKey) < 7
) As Under7Days
ON FinalWeeks.Week = Under7Days.Week
AND FinalWeeks.YearNo = Under7Days.YearNo
) SRC
ON TGT.DateID BETWEEN SRC.StartDate AND SRC.EndDate
Looks complicated? There's half a dozen ways to write the same thing but this approach is step-by-step. You could probably write a windowing function to do the same thing but I leave that as an exercise for someone else.

How do I correctly use the SQL Sum function with multiple variables and grouping?

I am trying to write an SQL statement based on the following code.
CREATE TABLE mytable (
year INTEGER,
month INTEGER,
day INTEGER,
hoursWorked INTEGER )
Assuming that each employee works multiple days over each month in a 3 year period.
I need to write an sql statement that returns the total hours worked in each month, grouped by earliest year/month first.
I tried doing this, but I don't think it is correct:
SELECT Sum(hoursWorked) FROM mytable
ORDER BY(year,month)
GROUP BY(month);
I am a little confused about how to operate the sum function in conjunction with thee GROUP BY or ORDER BY function. How does one go about doing this?
Try this:
SELECT year, month, SUM(hoursWorked)
FROM mytable
GROUP BY year, month
ORDER BY year, month
This way you will have for example:
2014 December 30
2015 January 12
2015 February 40
Fields you want to group by always have be present in SELECT part of query. And vice-versa - what you put in SELECT part, need be also in GROUP BY.
SELECT year, month, Sum(hoursWorked)as workedhours
FROM mytable
GROUP BY year,month
ORDER BY year,month;
You have to group by year and month.
Is this what you are trying to do. This will sum by Year/Month and Order by Year/Month.
Select [Year], [Month], Sum(HoursWorked) as WorkedHours
From mytable
Group By [Year], [Month]
Order by [Year], [Month]
You have to group by year and month, otherwise you will have the hours you worked on March 2014 and 2015 in one record :)
SELECT Sum(hoursWorked) as hoursWorked, year, month
FROM mytable
GROUP BY(year, month)
ORDER BY(year,month)
;