Exapansion of rows based on Calendar - sql-server

My fact table is following
declare #fact as TABLE (WO varchar(3), startYear int, startFiscalPeriod int, endFiscalPeriod int)
INSERT INTO #fact
Select WO, startYear,startFiscalPeriod, endFiscalPeriod
from
(
VALUES
('WO1', 2020, 202011, 202106),
('WO2', 2020, 202009, 202106),
('WO3', 2021, 202102, 202106)
) t (WO, startYear,startFiscalPeriod, endFiscalPeriod)
select * from #fact
WO
startYear
startFiscalPeriod
endFiscalPeriod
WO1
2020
202011
202106
WO2
2020
202009
202106
WO3
2021
202102
202106
I want to expand the rows based on the interval between startFiscalPeriod and endFiscalPeriod, like following
;with cte as
(select WO, startYear,startFiscalPeriod, endFiscalPeriod from #fact
UNION ALL
select WO, startYear,startFiscalPeriod+1,endFiscalPeriod from CTE
where startFiscalPeriod<[endFiscalPeriod])
However, I want the expansion to happen based on a calendarTable.
declare #Calendar as TABLE (fiscalYear int, periodNumber int, fiscalPeriod int)
INSERT INTO #Calendar
Select fiscalYear, periodNumber,fiscalPeriod
from
(
VALUES
(2020, 1, 202001),
(2020, 2, 202002),
(2020, 3, 202003),
(2020, 4, 202004),
(2020, 5, 202005),
(2020, 6, 202006),
(2020, 7, 202007),
(2020, 8, 202008),
(2020, 9, 202009),
(2020, 10, 202010),
(2020, 11, 202011),
(2020, 12, 202012),
(2021, 1, 202101),
(2021, 2, 202102),
(2021, 3, 202103),
(2021, 4, 202104),
(2021, 5, 202105),
(2021, 6, 202106)
) t (fiscalYear, periodNumber,fiscalPeriod)
My desired output is following which I can't generate by simply expanding the rows on simple do while logic. Is there any way to condition the do while logic based on the calendar?
WO
startYear
startFiscalPeriod
endFiscalPeriod
WO1
2020
202011
202106
WO1
2020
202012
202106
WO1
2020
202101
202106
WO1
2020
202102
202106
WO1
2020
202103
202106
WO1
2020
202104
202106
WO1
2020
202105
202106
WO1
2020
202106
202106
WO2
2020
202009
202106
WO2
2020
202010
202106
WO2
2020
202011
202106
WO2
2020
202012
202106
WO2
2020
202101
202106
WO2
2020
202102
202106
WO2
2020
202103
202106
WO2
2020
202104
202106
WO2
2020
202105
202106
WO2
2020
202106
202106
WO3
2021
202102
202106
WO3
2021
202103
202106
WO3
2021
202104
202106
WO3
2021
202105
202106
WO3
2021
202106
202106
Thank you in advance

Why not join the two tables with a between condition, like Calendar.fiscalPeriod between fact.startFiscalPeriod and fact.endFiscalPeriod?
select
f.WO
, f.startYear
, c.fiscalPeriod startFiscalPeriod
, f.endFiscalPeriod
from
#fact f
inner join #Calendar c on c.fiscalPeriod between f.startFiscalPeriod and f.endFiscalPeriod
order by
f.WO
, c.fiscalPeriod

Related

How to get the correct date format

How to get this date format in Snowflake?
"day; YYYY/MM/DD; HH:MM AM - HH:MM AM" format in snowflake
Tried these logic:
select current_date()
,to_char(DAY() , 'MMMM DD, YYYY')
,to_date (to_char(current_date() , 'MMMM DD, YYYY'), 'MMMM DD, YYYY')
;
select to_timestamp('2019-02-28 23:59:59.000000000 -07:00', 'YYYY-MM-DDHH24:MI:SS.FF TZH:TZM');
You question seems rather confused.
select to_timestamp_tz('2019-02-28 23:59:59.123400000 -07:00', 'YYYY-MM-DDHH24:MI:SS.FF TZH:TZM');
gives:
TO_TIMESTAMP_TZ('2019-02-28 23:59:59.123400000 -07:00', 'YYYY-MM-DDHH24:MI:SS.FF TZH:TZM')
2019-02-28 23:59:59.123 -0700
so it seems possible to parse the string to -> timestamp with timezone.
select
column1 as cd
,to_char(cd, 'MMMM DD, YYYY') as d1
,to_char(cd, 'DY; YYYY/MM/DD; HH:MI AM') as d2
FROM VALUES
(current_date),
(current_timestamp)
gives:
CD
D1
D2
2022-04-07 00:00:00.000 -0700
April 07, 2022
Thu; 2022/04/07; 00:00 AM
2022-04-07 00:39:13.433 -0700
April 07, 2022
Thu; 2022/04/07; 00:39 AM
Full Day:
So as noted in the comments there are a couple ways to get Day of Week:
select
current_date() as cd
,extract ('dayofweek_iso',current_date()) as dow_1
,dayofweekiso(cd) as dow_2
,decode(dow_1, 1, 'Monday', 2, 'Tuesday', 3, 'Wednesday', 4, 'Thursday', 5, 'Friday', 6, 'Saturday', 7, 'Sunday') as full_day;
CD
DOW_1
DOW_2
FULL_DAY
2022-04-07
4
4
Thursday
Full Output:
select
current_timestamp() as cd
,extract ('dayofweek_iso',current_date()) as dow_1
,dayofweekiso(cd) as dow_2
,decode(dow_1, 1, 'Monday', 2, 'Tuesday', 3, 'Wednesday', 4, 'Thursday', 5, 'Friday', 6, 'Saturday', 7, 'Sunday') as full_day
,full_day || to_char(cd, '; YYYY/MM/DD; HH:MI AM - HH:MI AM') as full_format;
gives:
CD
DOW_1
DOW_2
FULL_DAY
FULL_FORMAT
2022-04-07 14:57:11.717 -0700
4
4
Thursday
Thursday; 2022/04/07; 14:57 PM - 14:57 PM

SQL Server take a time duration and parse the time into the hour parts of that duration

I am posting this question again because the project has changed and the previous answers don't return the desired results. Ambulances and fire trucks have the dispatch time when an emergency occurred and an end time for when the emergency was declared over.
Event 1 starts on May 1, 2021 10:17:33 and ends at may 1, 2021 10:33:41.
Event 2 starts on May 1, 2021 11:50:52 and ends at May 1, 2021 13:18:21.
I would like to parse the amount of time from the start to the end and place it into the hour parts when it occurs. For example; Event 1 starts at 10:17 and ends at 10:33. It would place 16 minutes minutes in the 10:00 hour part for that day. Event 2 would place 10 minutes in the 11:00 hour part, 60 minutes in the 12:00 hour part and 18 minutes in the 13:00 hour part. Place the minutes in the hours during which the event occured.
The results should look the following. Although I am flexible. For example, if the name of the truck cannot be returned in the results that would be ok because if the EventID is there, I could relate back to the original table.
EventID
Ambulance
EventDayOfYear
EventHour
MinutesAllocated
1
Medic10
121
10
16
1
Medic10
121
11
10
2
Ladder73
121
11
10
2
Ladder73
121
12
60
2
Ladder73
121
13
18
3
Engine41
121
13
33
3
Engine41
121
14
21
4
Medic83
121
15
32
4
Medic83
121
16
5
5
Rescue32
121
16
33
6
Medic09
121
23
16
6
Medic09
122
0
39
7
Engine18
121
23
28
7
Engine18
122
0
60
7
Engine18
122
1
34
8
Rescue63
122
0
35
The following SQL code comes close to working to deliver the right result. But it does not overlap days. There are many emergency events that start at 2300 hours and last until 0300 hours the following day.
DECLARE #tempFireEvents TABLE
(
EventID INT NOT NULL
, Apparatus VARCHAR(10) NOT NULL
, StartDateTime DATETIME NOT NULL
, EndDateTime DATETIME NOT NULL
, DurationInSeconds INT NOT NULL
)
INSERT INTO #tempFireEvents
VALUES
(1, 'Medic10', 'may 1, 2021 10:17:33', 'may 1, 2021 10:33:41', 968) /*This event is entirely within 1000 hours*/
, (2, 'Ladder73', 'may 1, 2021 11:50:52', 'may 1, 2021 13:18:21', 5249) /*This event spans 1100, 1200 and 1300 hours*/
, (3, 'Engine41', 'may 1, 2021 13:27:17', 'may 1, 2021 14:21:18', 3241) /*This event overlaps 1300 and 1400 hours*/
, (4, 'Medic83', 'may 1, 2021 15:28:08', 'may 1, 2021 16:05:48', 2260) /*This event overlaps 1500 and 1600 hours*/
, (5, 'Rescue32', 'may 1, 2021 16:20:43', 'may 1, 2021 16:53:28', 1965) /*This event is entirely within the 1600 hour part*/
, (6, 'Medic09', 'may 1, 2021 23:44:06', 'may 2, 2021 00:39:52', 3346) /*Notice this overlaps the 2300 and 0000 hours into the following day*/
, (7, 'Engine18', 'may 1, 2021 23:32:58', 'may 2, 2021 01:34:13', 7275) /*Notice this overlaps the 2300, 0000 and 0100 hours into the following day*/
, (8, 'Rescue63', 'may 2, 2021 00:17:45', 'may 2, 2021 00:52:09', 2064) /*Notice this is the 00 hour of the day and does not show in the results*/
;
WITH AllHours AS
(
SELECT 1 AS hourInt
UNION ALL
SELECT hourInt + 1
FROM AllHours
WHERE hourInt < 23
)
,
Combined AS
(
SELECT
T.EventID
, H.hourInt
, CASE WHEN DATEPART(HOUR, T.StartDateTime) = H.hourInt THEN 1 ELSE 0 END AS isStart
, CASE WHEN DATEPART(HOUR, T.EndDateTime) = H.hourInt THEN 1 ELSE 0 END AS isEnd
, T.StartDateTime
, T.EndDateTime
FROM #tempFireEvents AS [T]
JOIN AllHours AS [H] ON H.hourInt BETWEEN DATEPART(HOUR, T.StartDateTime) AND DATEPART(HOUR,T.EndDateTime)
)
SELECT
EventID
, hourInt
, CASE WHEN isStart = 1 AND isEnd = 0 THEN 60 - DATEPART(MINUTE, StartDateTime)
WHEN isStart = 0 AND isEnd = 1 THEN DATEPART(MINUTE, EndDateTime)
WHEN isStart = 1 AND isEnd = 1 THEN DATEPART(MINUTE, EndDateTime) - DATEPART(MINUTE, StartDateTime)
ELSE 60
END AS MinutesInThisHour
FROM Combined
ORDER BY EventID ASC, hourint ASC
;
I have a suspiction that SQL Server may not be the best method to achieve the goal. It may need to be written in Python with increment and decrement and counters.
If it helps, I have a calendar table that looks like:
May 1, 2021 00:00:00
May 1, 2021 01:00:00
May 1, 2021 02:00:00
May 1, 2021 03:00:00
May 1, 2021 04:00:00
May 1, 2021 05:00:00
May 1, 2021 06:00:00
Would a calendar table be useful in solving this problem?
…
CREATE TABLE tempFireEvents
(
EventID VARCHAR(8) NOT NULL,
StartDateTime DATETIME NOT NULL,
EndDateTime DATETIME NOT NULL
)
INSERT INTO tempFireEvents
VALUES
('fire0001', 'november 1, 2018 10:45:00', 'november 2, 2018 11:30:00'),
('fire0002', 'november 1, 2018 11:50:00', 'november 1, 2018 13:10:00'),
('fire0003', 'november 1, 2018 13:20:00', 'november 1, 2018 14:20:00'),
('fire0004', 'november 1, 2018 15:25:00', 'november 1, 2018 16:05:00'),
('fire0005', 'november 1, 2018 16:20:00', 'november 2, 2018 17:00:00'),
('fire0006', 'november 1, 2018 16:20:00', 'november 1, 2018 17:01:00');
select e.*, hr.ld,
60 - case when e.startdatetime > hr.ld then datepart(minute, e.startdatetime) else 0 end
+ case when e.enddatetime < hr.ud then datepart(minute, e.enddatetime)-60 else 0 end as allocatedminutes
from tempFireEvents as e
cross apply
(
select
dateadd(hour, datepart(hour,e.startdatetime)+t.rn-1, cast(cast(e.startdatetime as date) as datetime)) as ld,
dateadd(hour, datepart(hour,e.startdatetime)+t.rn, cast(cast(e.startdatetime as date) as datetime)) as ud,
rn
from
(
-- a tally, max 100 rows .. max 100 hours duration
select top (1+datediff(hour,e.startdatetime,dateadd(minute, -1, e.enddatetime))) row_number() over(order by ##spid) as rn
from (values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) as a(n)
cross join (values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) as b(n)
) as t
) as hr;

How to generate employee timesheet in sql server

I have five tables:
Employees(EmpId, FirstName, LastName, DeptId,…)
Attendance(LogId, PunchIn, PunchOut,...)
Leave(RequestId, StartDate, endDate, LeaveType,...)
Holiday(HolidayId, Descriptions, StartDate, EndDate,....)
Business Travel(Request_Id, RequestDate, StartDate, EndDate,....)
I am trying to generate a monthly/Annual time-sheet report, time-sheet must represent an employee (or group of employees) status at the corresponding date like: on duty, later arrived, leave vacation, sick leave etc.
I create the following function
Create Function dbo.fn_GetEmployeeStatus(#LogDate Date, #BadgeNo int)
Returns char(3)
As
begin
Declare #status char(3) = null;
Declare #punchin DateTime;
Declare #punchout DateTime;
Declare #ShiftId tinyint;
Declare #LateEarly smallint;
Declare #id int = null;
Set #status = null;
Select #ShiftId = Shift_Id From Staff
Where Badge_No = Badge_No;
Select #id = Max(Holiday_Id) From Holiday
Where #LogDate Between StartDate And EndDate
if(#id is not null)
Set #status = 'HOL' --Holiday
else Set #status = null;
if(#status is null)
begin
Set #id = null;
Select #id = Max(Request_Id) From BusinessTravel
Where #LogDate Between Start_Date And End_Date
And Badge_No = #BadgeNo
if(#id is not null)
Set #status = 'BST' --Business Travel
else Set #status = null;
end
if(#status is null)
begin
Set #id = null;
Select #id = Max(LeaveCategory_Id) From Leaves
Where #LogDate Between Start_Date And End_Date
And Badge_No = #BadgeNo
if(#id is not null)
begin
Set #status = Case #id
When 1 Then 'ANV' --Annual Leave
When 2 Then 'SIC' --Sick leave
When 3 Then 'SLV' --Study leave
When 4 Then 'ELV' --Emergency leave
When 5 Then 'ULV' --Unpaid leave
When 6 Then 'HLV' --Haj Leave
When 7 Then 'MLV' --Marriage leave
When 8 Then 'DLV' --Death of a relative
When 9 Then 'PLV' --Paternity leave
When 7 Then 'MLV' --Materinty Leave
else 'UNK' end; --Unknown
end else Set #status = null;
end
if(#status is null)
begin
Select #punchin = Min(Log_Date), #punchout = Max(Log_Date) From AttendanceLog
Where Cast(Log_Date as Date) = #LogDate
And Badge_No = #BadgeNo
if(#punchin is not null)
begin
Select #LateEarly = dbo.fun_GetEarlyLateAmt(#punchin, 1, #ShiftId)
if(#LateEarly > 20)
begin
Select #LateEarly = dbo.fun_GetEarlyLateAmt(#punchout, 0, #ShiftId)
if(#LateEarly > 10)
Set #status = 'L&E'; --Late Arrive & Early left
else Set #status = 'LTE'; --Late Arrive
end else Set #status = 'ODU'; --On Duty
end --else Set #status = null;
end
if(#status is null)
begin
if ((DatePart(dw, #LogDate) + ##DateFirst) % 7) in(0, 6)
Set #status = 'WKE'; --Weekend
Set #status = 'ABS';
end --else Set #status = 'ABS';
Return #status;
end
--But the following failed
Declare
#BadgeNo int = 2523,
#Year int = 2019
;With data as (
Select DateName(month, InTime) Mon, LogInDay = DATEPART(DAY, DATEADD(HOUR, -6, InTime))
,LogYear = DATEPART(YEAR, InTime), LogMonth = DATEPART(MONTH, InTime),
dbo.fn_GetEmployeeStatus_2(InTime, Badge_No) eStatus From v_EmpAttendanceStatus--v_AttendanceLog
Where DATEPART(YEAR, InTime) = #Year
And Badge_No = #BadgeNo)
Select Mon, LogYear, LogMonth, IsNull([1], 0)[1], IsNull([2], 0)[2], IsNull([3], 0)[3], IsNull([4], 0)[4], IsNull([5], 0)[5], IsNull([6], 0)[6], IsNull([7], 0)[7], IsNull([8], 0)[8], IsNull([9], 0)[9], IsNull([10], 0)[10], IsNull([11], 0)[11], IsNull([12], 0)[12], IsNull([13], 0)[13], IsNull([14], 0)[14], IsNull([15], 0)[15], IsNull([16], 0)[16], IsNull([17], 0)[17], IsNull([18], 0)[18], IsNull([19], 0)[19], IsNull([20], 0)[20], IsNull([21], 0)[21], IsNull([22], 0)[22], IsNull([23], 0)[23], IsNull([24], 0)[24], IsNull([25], 0)[25], IsNull([26], 0)[26], IsNull([27], 0)[27], IsNull([28], 0)[28], IsNull([29], 0)[29], IsNull([30], 0)[30], IsNull([31], 0)[31]
From data
Pivot (
Max(eStatus)
For LogInDay In
([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30], [31])
) as piv
Order By LogMonth
Above cte result not shown holidays and leave vacation. I need the report like bellow image.
--Sample Data
1- Employee Table:
#Badge_No FirstName LastName DeptId#
2523 Name1 Last1 1001
2524 Name2 Last2 1001
2525 Name3 Last3 1006
-------------------------------------------------------------------
2- Holiday Table:
ID Sescriprions StartDate EndDate
1 Holidy1 '02 Jun 2019' '08 Jun 2019'
1 Holidy2 '23 Sep 2019' '24 Sep 2019'
---------------------------------------------------------------------
3- Leave Table:
#Request_Id Badge_No StartDate EndDate LeaveCategory#
1 2525 '15 Dec 2018' '22 Jan 2019' 2 --Sick leave
...
101 2524 '01 Jan 209' '03 Jan 209' 2 --Sick Leave
2061 2523 '09 Jun 2019' '04 Jul 2019' 1 --Annual Leave
..
2125 2523 '22 Jul 2019' '22 Jul 2019' 5 --Unpaid leave
--------------------------------------------------------------
4- Attendance Table:
#Badge_No Punch-In Punch-Out Shift_Id#
2523 '01 Jan 2019 07:04' '01 Jan 2019 16:01' 1
2524 '01 Jan 2019 07:45 '01 Jan 2019 15:56' 1
.......
2523 '28 Jan 2019 06:50' '28 Jan 2019 16:03' 1
2524 '28 Jan 2019 07:02' '28 Jan 2019 16:00' 1
2525 '28 Jan 2019 07:42' '28 Jan 2019 16:00' 1
2523 '29 Jan 2019 07:30' '29 Jan 2019 15:59' 1
2524 '29 Jan 2019 06:58' '29 Jan 2019 16:01' 1
2523 '30 Jan 2019 07:13' '30 Jan 2019 07:18' 1
2525 '30 Jan 2019 09:18' '30 Jan 2019 07:18' 1
2524 '30 Jan 2019 08:11' '30 Jan 2019 16:00' 1
2525 '30 Jan 2019 10:26' '30 Jan 2019 16:00' 1
2523 '31 Jan 2019 11:27' '31 Jan 2019 15:54' 1
2524 '31 Jan 2019 07:02' '31 Jan 2019 15:51' 1
.......
2523 '25 Jul 2019 08:17' '25 Jul 2019 17:23' 1
--------------------------------------------------------------
5- BusinessTravel Table:
#Badge_No StartDate EndDate#
2523 '07 Jan 2019' '09 Jan 2019'
2525 '03 Mar 2019' '07 Mar 2019'

Split string in columns by delimiter using SQL Server

I need to split my one column value in column using delimiter, below is the table structure.
create table #a
(
id int,
timeline varchar(100)
)
insert into #a
values (1, 'Semi Annual Q2 (May/June/July) & Q4 (Nov/Dec/Jan)'),
(2, 'Semi Annual Q1 (Feb/Mar/Apr) & Q3 (Aug/Sep/Oct)'),
(3, 'Annual Q3 (Aug/Sep/Oct)'),
(4, 'Annual Q2 (May/June/July)'),
(5, 'Annual Q4 (Nov/Dec/Jan)'),
(6, 'Semi Annual Q1 (Jan/Feb/Mar) & Q3 (July/Aug/Sep)')
select * from #a
Output I want to split timeline values by ' / ' delimiter and make separate column for separate month and all month should be in sequence, which look like a below sample.
ID M1 M2 M3 M4 M5 M6
---------------------------------------
1 May June July Nov Dec Jan
2 Feb Mar Apr Aug Sep Oct
3 Aug Sep Oct NULL NULL NULL
4 May June July NULL NULL NULL
5 Nov Dec Jan NULL NULL NULL
6 Jan Feb Mar July Aug Sep
So far, I have tried this:
select
timeline,
substring((substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline) - 1)), 1, charindex('/', substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline) - 1)) - 1) as M1,
replace(replace(right(substring(substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline)), 1, charindex(')', substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline)))), charindex('/', reverse(substring(substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline)), 1, charindex(')', substring(timeline, CHARINDEX('(', timeline) + 1, len(timeline))))), 4)), '/', ''), ')', '') as M3
from
#a;
which is not a code and too tedious also. please help if you have efficient way to do this.
The SplitCSVToTable8K function being used in the following solution, is the same DelimitedSplit8K function mentioned above...
Here's how to use it in the solution:
WITH
cte_ParseTimeline AS (
SELECT
a.id,
rn = ROW_NUMBER() OVER (PARTITION BY a.id ORDER BY sc.ItemNumber),
sc.Item
FROM
#a a
CROSS APPLY dbo.SplitCSVToTable8K(REPLACE(REPLACE(a.timeline, '(', '/'), ')', '/'), '/') sc
WHERE
sc.Item LIKE ('[A-Z][a-z][a-z]')
OR
sc.Item LIKE ('[A-Z][a-z][a-z][a-z]')
)
SELECT
pt.id,
M1 = MAX(CASE WHEN pt.rn = 1 THEN pt.Item END),
M2 = MAX(CASE WHEN pt.rn = 2 THEN pt.Item END),
M3 = MAX(CASE WHEN pt.rn = 3 THEN pt.Item END),
M4 = MAX(CASE WHEN pt.rn = 4 THEN pt.Item END),
M5 = MAX(CASE WHEN pt.rn = 5 THEN pt.Item END),
M6 = MAX(CASE WHEN pt.rn = 6 THEN pt.Item END)
FROM
cte_ParseTimeline pt
GROUP BY
pt.id;
Results...
id M1 M2 M3 M4 M5 M6
----------- ----- ----- ----- ----- ----- -----
1 May June July Nov Dec Jan
2 Feb Mar Apr Aug Sep Oct
3 Aug Sep Oct NULL NULL NULL
4 May June July NULL NULL NULL
5 Nov Dec Jan NULL NULL NULL
6 Jan Feb Mar July Aug Sep

Get last 6 months monthname.month number and Years in simple select statement

How to get last 6 months month name, month number and Years in simple select statement in sqlserver .
The no of months is 6, and is fixed
12 Dec 2015
11 Nov 2015
10 Oct 2015
9 Sep 2015
8 Aug 2015
7 Jul 2015
6 Jun 2015
This should handle year end boundaries
say, if the current month is Feb 2016, the result should give 2015 months.
2 Feb 2016
1 Jan 2016
12 Dec 2015
11 Nov 2015
10 Oct 2015
9 Sep 2015
8 Aug 2015
You can do it with the following:
SELECT MONTH(DATEADD(mm, -m, GETDATE())) AS m,
LEFT(DATENAME(mm, DATEADD(mm, -m, GETDATE())), 3) AS n,
YEAR(DATEADD(mm, -m, GETDATE())) AS y
FROM (VALUES (0),(1),(2),(3),(4),(5),(6)) t(m)
Output:
m n y
12 Dec 2015
11 Nov 2015
10 Oct 2015
9 Sep 2015
8 Aug 2015
7 Jul 2015
6 Jun 2015
Try this
;with cte as
(
select 0 as num
union all
select num+1 from cte where num<6
)
select month(dates),datename(month,dates),year(dates)
from
(
select dateadd(mm,-num,datadd(dd,1,eomonth(getdate(),-1))) as dates
from cte
) A
SQL FIDDLE DEMO
select datepart(m,GETDATE()) MonthNumber,left(datename(month,GETDATE()),3) as Month,year(GETDATE()) as Year union all
select datepart(m,DATEADD(month,-1,GETDATE())) MonthNumber,left(datename(month,DATEADD(month,-1,GETDATE())),3) as Month,year(DATEADD(month,-1,GETDATE())) as Year union all
select datepart(m,DATEADD(month,-2,GETDATE())) MonthNumber,left(datename(month,DATEADD(month,-2,GETDATE())),3) as Month,year(DATEADD(month,-2,GETDATE())) as Year union all
select datepart(m,DATEADD(month,-3,GETDATE())) MonthNumber,left(datename(month,DATEADD(month,-3,GETDATE())),3) as Month,year(DATEADD(month,-3,GETDATE())) as Year union all
select datepart(m,DATEADD(month,-4,GETDATE())) MonthNumber,left(datename(month,DATEADD(month,-4,GETDATE())),3) as Month,year(DATEADD(month,-4,GETDATE())) as Year union all
select datepart(m,DATEADD(month,-5,GETDATE())) MonthNumber,left(datename(month,DATEADD(month,-5,GETDATE())),3) as Month,year(DATEADD(month,-5,GETDATE())) as Year union all
select datepart(m,DATEADD(month,-6,GETDATE())) MonthNumber,left(datename(month,DATEADD(month,-6,GETDATE())),3) as Month,year(DATEADD(month,-6,GETDATE())) as Year
The above query will work for most of the RDBMS.
For SQL Server specific use the below query.
SELECT MONTH(DATEADD(month, -month, GETDATE())) AS MonthNumber ,
LEFT(DATENAME(MONTH, DATEADD(month, -month, GETDATE())), 3) AS MonthName,
YEAR(DATEADD(month, -month, GETDATE())) AS Year
FROM ( VALUES (0), (1), (2), (3), (4), (5),(6) ) t ( month )
Try DATEADD:
Select * FROM Table where YourDate>=DATEADD(m, -6, GETDATE())

Resources