Dynamic column name change based on date [T-SQL] - sql

Is there a way to make this work? change static, "13MonthsAgo"
into January?
Original
> COUNT(CASE WHEN dateadd(MONTH, - 13, getdate()) >
> HireDate AND dateadd(MONTH, - 13, getdate()) <
> TerminationDate OR
>TerminationDate IS NULL THEN 1 ELSE NULL END) AS 13Monthsago
Preferred
> COUNT(CASE WHEN dateadd(MONTH, - 13, getdate()) >
> HireDate AND dateadd(MONTH, - 13, getdate()) <
> TerminationDate OR
>TerminationDate IS NULL THEN 1 ELSE NULL END) AS
>DATENAME(month, dateadd(MONTH,-13,getdate()))

A lengthy approach but will work..
declare #MonthName varchar(20)
select 1 num, 'January' name into #Months
union
select 2 num, 'February' name
union
select 3 num, 'March' name
union
select 4 num, 'April' name
union
select 5 num, 'May' name
union
select 6 num, 'June' name
union
select 7 num, 'July' name
union
select 8 num, 'August' name
union
select 9 num, 'September' name
union
select 10 num, 'October' name
union
select 11 num, 'November' name
union
select 12 num, 'December' name
select #MonthName = name from #Months where datepart(mm,getdate()) = num
--Add the other columns to the dataset here
--This is just an example
select HireDate, TerminationDate,
COUNT(CASE WHEN dateadd(MONTH, - 13, getdate()) >
HireDate AND dateadd(MONTH, - 13, getdate()) <
TerminationDate OR
TerminationDate IS NULL THEN 1 ELSE NULL END) AS 13Monthsago
into #Dataset
FROM SomeTable GROUP BY HireDate, TerminationDate
use tempdb
EXEC sp_RENAME '#Dataset.13Monthsago' , #MonthName, 'COLUMN'
SELECT * FROM #Dataset

This could be one way to go about it.
;with cte_Dates AS
(
SELECT CAST('20150101' as DATEtime) as DateStr UNION ALL
SELECT '20150201' UNION ALL
SELECT '20150202' UNION ALL
SELECT '20150203' UNION ALL
SELECT '20150204' UNION ALL
SELECT '20150301' UNION ALL
SELECT '20150401' UNION ALL
SELECT '20150501' UNION ALL
SELECT '20150601' UNION ALL
SELECT '20150701' UNION ALL
SELECT '20150801' UNION ALL
SELECT '20150901' UNION ALL
SELECT '20151001' UNION ALL
SELECT '20151101' UNION ALL
SELECT '20151201'
)
SELECT *
FROM
(SELECT DateStr,DATENAME(MONTH,DateStr) As MONTHS
FROM
cte_Dates
)P
PIVOT
(
count(DateStr)
FOR MONTHS IN ([January], [February],[March],[April],[May],[June],[July],[August],[September],[October],[November],[December])
)AS PVT

Related

SQL Query to Calculate Monthly Budget

CREATE TABLE [dbo].[EmployeeMonthlyBudget]
(
[Name] [NVARCHAR](50) NULL,
[Budget_Day] [MONEY] NULL,
[DateCreated] [DATETIME] NULL,
[DateDeleted] [DATETIME] NULL
)
INSERT INTO [dbo].[EmployeeMonthlyBudget] ([Name], [Budget_Day], [DateCreated], [DateDeleted])
VALUES (N'SAM', 20.0000, CAST(N'2018-01-01T00:00:00.000' AS DateTime), CAST(N'2018-10-01T00:00:00.000' AS DateTime)),
(N'ROB', 10.0000, CAST(N'2018-01-01T00:00:00.000' AS DateTime), NULL),
(N'TAM', 5.0000, CAST(N'2018-01-01T00:00:00.000' AS DateTime), CAST(N'2018-05-01T00:00:00.000' AS DateTime)),
(N'TAN', 100.0000, CAST(N'2018-01-01T00:00:00.000' AS DateTime), NULL)
The above is the table structure we had to calculate monthly budget.
We are displaying the bar graph for each name how their monthly budget is.
Suppose if we take Sam his budget for Jan is 620 and Feb is 580 and so on, So we need to calculate the budget for each month until DateDeleted has value
We are able to calculate the budget per month for each Employee Name, but unable
to figure out how to calculate them for consecutive months.
Please, anyone, help me on this
How to write SQL for the above approach.
Please sample table data
Hope this helps
SELECT A.Name,A.budget_day,B.MonthName,B.totaldays*A.budget_day as MonthlySpent
FROM
[dbo].[EmployeeMonthlyBudget] A
inner join(
SELECT [Name] , DATENAME(MONTH, DATEADD(MONTH, nos.monthnos, [DateCreated])-1) AS MonthName,DAY(EOMONTH(DATEADD(MONTH, nos.monthnos, [DateCreated])-1)) as totaldays,month(EOMONTH(DATEADD(MONTH, nos.monthnos, [DateCreated])-1)) as monthOrder
from [dbo].[EmployeeMonthlyBudget]
inner join (SELECT 1 monthnos UNION SELECT 2 UNION SELECT 3
UNION SELECT 4 UNION SELECT 5 UNION SELECT 6
UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
UNION SELECT 10 UNION SELECT 11 UNION SELECT 12) nos on nos.monthnos <= DATEDIFF(MONTH, [DateCreated],isnull([DateDeleted],GETDATE()))+1
) B on
A.NAME=B.Name
order by A.Name,monthOrder
Try This
select name,budget_day,monthname,totalspent from
(Select j.* ,row_number () over (partition by j.name,j.monthname order by j.totalspent) as rn
from
(Select B.name,A.budget_day,MonthName,(datediff(day,[DateCreated],DefaultDate)+1)*A.budget_day as TotalSpent,monthOrder
from (SELECT
*, [Budget_Day]*DATEDIFF(day,[DateCreated],isnull([DateDeleted],GETDATE())) as TotalSpent, DATENAME(MONTH, [DateCreated]) AS MonthNameStart, DATENAME(MONTH,isnull([DateDeleted],GETDATE())) AS MonthNameEND
from
[dbo].[EmployeeMonthlyBudget]
where datecreated<=isnull(datedeleted,getdate())) A
LEFT join
(
SELECT [Name] , DATENAME(MONTH, DATEADD(MONTH, nos.monthnos-1, [DateCreated])) AS MonthName,EOMONTH([DateCreated]) as DefaultDate ,
DAY(EOMONTH(DATEADD(MONTH, nos.monthnos, [DateCreated])-1)) as totaldays,
month(DATEADD(MONTH, nos.monthnos-1, [DateCreated])) as monthOrder
from [dbo].[EmployeeMonthlyBudget]
inner join (SELECT 1 monthnos UNION SELECT 2 UNION SELECT 3
UNION SELECT 4 UNION SELECT 5 UNION SELECT 6
UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
UNION SELECT 10 UNION SELECT 11 UNION SELECT 12) nos on nos.monthnos <= DATEDIFF(MONTH, [DateCreated],isnull([DateDeleted],GETDATE()))
) B
on A.MonthNameStart =B.MonthName and
A.Name=B.name
UNION
Select B.name,A.budget_day,MonthName,((datediff(day,DefaultDate,isnull([Datedeleted],getdate())))+1)*A.budget_day as TotalSpent,monthOrder from
(SELECT
*, [Budget_Day]*DATEDIFF(day,[DateCreated],isnull([DateDeleted],GETDATE())) as TotalSpent, DATENAME(MONTH, [DateCreated]) AS MonthNameStart, DATENAME(MONTH,isnull([DateDeleted],GETDATE())) AS MonthNameEND
from
[dbo].[EmployeeMonthlyBudget]
where datecreated<=isnull(datedeleted,getdate())) A
inner join
(SELECT [Name] , DATENAME(MONTH, DATEADD(MONTH, nos.monthnos, [DateCreated])-1) AS MonthName,DATEADD(month, DATEDIFF(month, 0, isnull([DateDeleted],getdate())), 0) as DefaultDate,
DAY(EOMONTH(DATEADD(MONTH, nos.monthnos, [DateCreated])-1)) as totaldays,
month(EOMONTH(DATEADD(MONTH, nos.monthnos, [DateCreated])-1)) as monthOrder
from [dbo].[EmployeeMonthlyBudget]
inner join (SELECT 1 monthnos UNION SELECT 2 UNION SELECT 3
UNION SELECT 4 UNION SELECT 5 UNION SELECT 6
UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
UNION SELECT 10 UNION SELECT 11 UNION SELECT 12) nos on nos.monthnos <= DATEDIFF(MONTH, [DateCreated],isnull([DateDeleted],GETDATE()))+1) B
on A.MonthNameEND =B.MonthName and A.Name=B.name
UNION
SELECT B.name,A.budget_day,MonthName,totaldays*A.budget_day as TotalSpent ,monthOrder
FROM
[dbo].[EmployeeMonthlyBudget] A
inner join(
SELECT [Name] , DATENAME(MONTH, DATEADD(MONTH, nos.monthnos-1, [DateCreated])) AS MonthName,EOMONTH([DateCreated]) as DefaultDate ,
DAY(EOMONTH(DATEADD(MONTH, nos.monthnos-1, [DateCreated]))) as totaldays,
month(DATEADD(MONTH, nos.monthnos-1, [DateCreated])) as monthOrder
from [dbo].[EmployeeMonthlyBudget]
inner join (SELECT 1 monthnos UNION SELECT 2 UNION SELECT 3
UNION SELECT 4 UNION SELECT 5 UNION SELECT 6
UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
UNION SELECT 10 UNION SELECT 11 UNION SELECT 12) nos on nos.monthnos <= DATEDIFF(MONTH, [DateCreated],isnull([DateDeleted],GETDATE()))
where datecreated<=isnull(datedeleted,getdate())
) B on
A.NAME=B.Name
)j)k
where k.rn=1 and k.name is not null
order by k.name,k.monthOrder

Create financial report with SQL

I want to create a financial report using a select statement for example: my start month is april 2000 and the end month is march 2001 how can I do that?
SELECT monthList.MonthName ,transcation.id,transaction.amount(
SELECT 10 ordby, 'January' MonthName
UNION SELECT 11, 'February'
UNION SELECT 12, 'March'
UNION SELECT 1, 'April'
UNION SELECT 2,'May'
UNION SELECT 3,'June'
UNION SELECT 4,'July'
UNION SELECT 5,'August'
UNION SELECT 6,'September'
UNION SELECT 7,'October'
UNION SELECT 8,'November'
UNION SELECT 9,'December') monthList
left JOIN (select YEAR(Date) [Year], MONTH(Date) [Month],DATENAME(MONTH,Date) [Month Name],sum(Amount)as amount
FROM transaction
where id=2 GROUP BY YEAR(Date), MONTH(Date),DATENAME(MONTH, Date) ) as t on t.[Month Name]=monthList.[Month Name])

SQL Convert Week Number to Date (dd/MM)

I am trying to convert the week number (for example: 21) in SQL-Server to the date (from the Monday of that week) in dd/MM format.
I have searched online but cannot seem to find anything that I could use.
Is this something I can do?
Any help or advice is appreciated.
Thank you in advance.
Try this,
declare #wk int set #wk = 21
declare #yr int set #yr = 2016
select dateadd (week, #wk-1, dateadd (year, #yr-1900, 0)) - 4 -
datepart(dw, dateadd (week, #wk-1, dateadd (year, #yr-1900, 0)) - 4) + 1
or try this way
declare #wk int = 21
select dateadd(week,#wk-1, DATEADD(wk, DATEDIFF(wk,-1,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)), 0))
You can do it something like:
declare #Week_Number int, #Year int, #Year_Start_Day date, #Week_Day date
select
#Week_Number = 1,
#Year = 2016
select #Year_Start_Day = cast(#Year as nvarchar(4)) + '0101'
select #Week_Day = dateadd(wk, #Week_Number, #Year_Start_Day)
select dateadd(dd, 1 - datepart(weekday, #Week_Day), #Week_Day)
This will do:
DECLARE #y int = 2016,
#w int = 21
SELECT CONVERT(nvarchar(5),DATEADD(day,#w*7-(DATEPART(WEEKDAY,CAST(#y as nvarchar(4))+'-01-01')-2),CAST(#y as nvarchar(4))+'-01-01'),3)
Output:
23/05
How about this?
DECLARE #YearNum SMALLINT = 2016;
DECLARE #WeekNum TINYINT=25;
select
SUBSTRING(CONVERT(VARCHAR(10),selected_date,105),0,6) AS WeeKDate
from
(select DATEADD(dd,t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i,'1970-01-01') selected_date from
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) v
where YEAR(selected_date)=#YearNum
AND DATEPART(WK,selected_date)=#WeekNum
AND DATEPART(WEEKDAY,selected_date)=2 -- Monday

How to select month wise data for year from sql server

I have a user table where data is about 20 years old.
I want to fetch month wise data from CreatedOn column that is (2014-07-08 17:44:00) and if data is not available for any month then I want 0 for this month
Example
Month data year
jan 34 2014
feb 56 2014
march 0 2014
apr 23 2014
I am using the following query but it's not working:
with cte(monno , monname ) as(
select 1, 'Jan' union all
select 2, 'Feb' union all
select 3, 'Mar' union all
select 4, 'Apr' union all
select 5, 'May' union all
select 6, 'Jun' union all
select 7, 'Jul' union all
select 8, 'Aug' union all
select 9, 'Sep' union all
select 10, 'Oct' union all
select 11, 'Nov' union all
select 12, 'Dec'
)
SELECT DISTINCT monname
,monno
,count(CreatedOn) OVER (PARTITION BY datepart(year, CreatedOn),DATEPART(MONTH, CreatedOn))
FROM Contributors_tbl a
RIGHT JOIN cte b ON DATEPART(MONTH, CreatedOn) = b.monno
AND datepart(year, CreatedOn) = 2014
ORDER BY monno
Try this Way to find Month Number AND Month Name
CREATE TABLE #TempMonth
(
MonthNum int,
MonthNames varchar(50)
)
INSERT INTO #TempMonth
SELECT STR(MONTH(DATEADD(mm, number, GETDATE())), 2) AS MonthNum,
DATENAME(month, DATEADD(month, MONTH(DATEADD(mm, number, GETDATE())), 0) - 1) AS MonthNames
FROM master.dbo.spt_values
WHERE (name IS NULL) AND (number BETWEEN 0 AND 11) ORDER BY STR(MONTH(DATEADD(mm, number, GETDATE())), 2)
SELECT * FROM #TempMonth
select distinct MonthNames,MonthNum,
count(CreatedOn) over(partition by datepart(year,CreatedOn),DATEPART(MONTH,CreatedOn))
from Contributors_tbl a
right join #TempMonth b on DATEPART(MONTH,CreatedOn) = b.MonthNum and datepart(year,CreatedOn) = 2014
order by MonthNum
DROP Table #TempMonth
Try This
with cte(monno , monname ) as(
select 1, 'Jan' union all
select 2, 'Feb' union all
select 3, 'Mar' union all
select 4, 'Apr' union all
select 5, 'May' union all
select 6, 'Jun' union all
select 7, 'Jul' union all
select 8, 'Aug' union all
select 9, 'Sep' union all
select 10, 'Oct' union all
select 11, 'Nov' union all
select 12, 'Dec'
)
select monname,
monno,
coalesce(cnt,0) as cnt
from cte c
outer apply (
select count(*) as cnt
from Contributors_tbl
where CreatedOn >= DATEADD(mm,c.monno - 1,'20140101')
And CreatedOn < DATEADD(mm,c.monno,'20140101')
)t
order by monno

Calculating a summary of previously calculated data

Quick question about summary data:
I have the below code which will pull sales information and put it into a month/year grid, which is terrific (http://sqlfiddle.com/#!3/9d79e/1):
WITH
months AS (SELECT 1 AS mon UNION ALL SELECT mon + 1 FROM months WHERE mon < 12),
years AS (SELECT 2011 AS yr UNION ALL SELECT yr + 1 FROM years WHERE yr < 2015),
invoices AS (
SELECT CAST('2013-06-27' AS date) AS InvoiceDate, 40 AS MarginAmount
UNION
SELECT CAST('2013-07-29' AS date) AS InvoiceDate, 40 AS MarginAmount
UNION
SELECT CAST('2013-10-30' AS date) AS InvoiceDate, 40 AS MarginAmount
)
-- End data setup, real work begins here
SELECT * FROM
(
SELECT
months.mon, years.yr, COALESCE(SUM(inv.MarginAmount), 0) AS MarginAmount
FROM
months
CROSS JOIN years
LEFT OUTER JOIN invoices inv ON ( (YEAR(inv.InvoiceDate) = years.yr) AND (MONTH(inv.InvoiceDate) = months.mon) )
GROUP BY
months.mon, years.yr
) AS source
PIVOT
(
MAX(MarginAmount)
FOR yr in ([2011], [2012], [2013], [2014], [2015])
)
AS pvt
ORDER BY mon
I was wondering how I could change two things:
Replace the numbers 1 - 11 with the names of the months of the year and
Create a line at the bottom of the table summarizing the information above it, where the mon column would have the word 'Total'
Any help would be greatly appreciated
e.g The sum of all sales in 2012 would be displayed at the bottom of the 2012 column
Question 1. Replace numbers
To replace the numbers, you can for instance change this:
months AS (SELECT 1 AS mon UNION ALL SELECT mon + 1 FROM months WHERE mon < 12)
to
months AS (SELECT 1 AS mon, 'Jan' name UNION ALL SELECT mon + 1, months.name FROM months WHERE mon < 12)
Question 2. Grand totals
To create a bottom line with totals you can either use grouping sets (your query seems to be SQL Server, don't know whether SQL Server supports that, please specify):
group
by grouping sets
( ()
, (full list)
)
or add a union to the query:
with myresults as (the whole thing)
select 1 ordering
, myresults.columns-minus-total
, myresults.something subtotal
from myresults
union all
select 2 ordering
, myresults.columns-minus-total
, sum(something) grandtotal
from myresults
order
by 1
, ...other...
Complete example using Microsoft SQL Server 2008 R2
Original code was prettified and without dependencies on tables:
with months as
( select 1 as mon
, 'Jan' monname
union all
select 2
, 'Feb'
union all
select 3
, 'Mar'
union all
select 4
, 'Apr'
union all
select 5
, 'May'
union all
select 6
, 'Jun'
union all
select 7
, 'Jul'
union all
select 8
, 'Aug'
union all
select 9
, 'Sep'
union all
select 10
, 'Oct'
union all
select 11
, 'Nov'
union all
select 12
, 'Dec'
)
, years as
( select 2011 as yr
union all
select 2012
union all
select 2013
union all
select 2014
)
, invoices as
( select cast('2013-06-27' as date) as invoicedate
, 40 as marginamount
union
select cast('2013-07-29' as date) as invoicedate
, 40 as marginamount
union
select cast('2013-10-30' as date) as invoicedate
, 40 as marginamount
)
select *
from ( select months.mon
, years.yr
, coalesce(sum(inv.marginamount), 0) as marginamount
from months
cross
join years
left
outer
join invoices inv
on year(inv.invoicedate) = years.yr
and month(inv.invoicedate) = months.mon
group
by months.mon
, years.yr
) source
pivot ( max(marginamount)
for yr
in ( [2011], [2012], [2013], [2014], [2015]
)
) pvt
order
by mon
Adding the text and grand totals leads to:
with months as
( select 1 as mon
, 'Jan' monname
union all
select 2
, 'Feb'
union all
select 3
, 'Mar'
union all
select 4
, 'Apr'
union all
select 5
, 'May'
union all
select 6
, 'Jun'
union all
select 7
, 'Jul'
union all
select 8
, 'Aug'
union all
select 9
, 'Sep'
union all
select 10
, 'Oct'
union all
select 11
, 'Nov'
union all
select 12
, 'Dec'
)
, years as
( select 2011 as yr
union all
select 2012
union all
select 2013
union all
select 2014
)
, invoices as
( select cast('2013-06-27' as date) as invoicedate
, 40 as marginamount
union
select cast('2013-07-29' as date) as invoicedate
, 40 as marginamount
union
select cast('2013-10-30' as date) as invoicedate
, 40 as marginamount
)
select case
when mon is null
then 'Total'
else cast(mon as varchar)
end
, monname
, [2011]
, [2012]
, [2013]
, [2014]
, [2015]
from ( select months.mon
, months.monname
, years.yr
, coalesce(sum(inv.marginamount), 0) as marginamount
from months
cross
join years
left
outer
join invoices inv
on year(inv.invoicedate) = years.yr
and month(inv.invoicedate) = months.mon
group
by grouping sets
( (months.mon, months.monname, years.yr)
, (years.yr)
)
) source
pivot ( max(marginamount)
for yr
in ( [2011], [2012], [2013], [2014], [2015]
)
) pvt
order
by coalesce(mon, 100)