Related
I want to sort data by weeks for previous month and I look for code which is usable automatic without manually writing the dates.
Instead of this:
SELECT
wadat_ist AS 'frame'
,CASE
WHEN wadat_ist BETWEEN '2019-09-01' AND '2019-09-01' THEN 'MA1'
WHEN wadat_ist BETWEEN '2019-09-02' AND '2019-09-08' THEN 'MA2'
WHEN wadat_ist BETWEEN '2019-09-09' AND '2019-09-15' THEN 'MA3'
WHEN wadat_ist BETWEEN '2019-09-16' AND '2019-09-22' THEN 'MA4'
WHEN wadat_ist BETWEEN '2019-09-23' AND '2019-09-30' THEN 'MA5'
END AS 'Activity'
I tried this:
SELECT
wadat_ist AS 'frame'
,CASE
WHEN wadat_ist BETWEEN (SELECT (Convert (DATETIME, (SELECT DATEADD(DAY,1,EOMONTH(GETDATE(),-2)))))) AND (SELECT DateAdd (wk, 0, (select DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, +0.99999)))) THEN 'MA1'
WHEN wadat_ist BETWEEN (SELECT DateAdd (wk, -4, (SELECT DATEADD(day,-1,DATEadd(MONTH,datediff(month,0,GETDATE()),0))))) AND (SELECT DateAdd (wk, 1, (select DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0)))) THEN 'MA2'
WHEN wadat_ist BETWEEN (SELECT DateAdd (wk, -3, (SELECT DATEADD(day,-1,DATEadd(MONTH,datediff(month,0,GETDATE()),0))))) AND (SELECT DateAdd (wk, 2, (select DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0)))) THEN 'MA3'
WHEN wadat_ist BETWEEN (SELECT DateAdd (wk, -2, (SELECT DATEADD(day,-1,DATEadd(MONTH,datediff(month,0,GETDATE()),0))))) AND (SELECT DateAdd (wk, 3, (select DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0)))) THEN 'MA4'
WHEN wadat_ist BETWEEN (SELECT DateAdd (wk, -1, (SELECT DATEADD(day,-1,DATEadd(MONTH,datediff(month,0,GETDATE()),0))))) AND (SELECT DateAdd (wk, 4, (select DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0)))) THEN 'MA5'
END AS 'Activity'
But the results are quite different. Values from first week are in the second week, values from second week are in the third and so on .. .all weeks are shifted somehow... Furthmore first week (MA1) is marked as NULL but his values should go to last week (MA5).
Plus I find this one, but it counts few weeks into one, but as the time goes, it matches to the rigt week, so maybe on the first of november will be fine, but I rather need something that will show data anytime in month.
WHEN wadat_ist BETWEEN (select DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0)) AND (select dateadd(wk, datediff(wk, 5, getdate()) - 5, 6)) THEN 'MA1'
WHEN wadat_ist BETWEEN (select dateadd(wk, datediff(wk, 4, getdate()) - 4, 0)) AND (select dateadd(wk, datediff(wk, 4, getdate()) - 4, 6)) THEN 'MA2'
WHEN wadat_ist BETWEEN (select dateadd(wk, datediff(wk, 3, getdate()) - 3, 0)) AND (select dateadd(wk, datediff(wk, 3, getdate()) - 3, 6)) THEN 'MA3'
WHEN wadat_ist BETWEEN (select dateadd(wk, datediff(wk, 2, getdate()) - 2, 0)) AND (select dateadd(wk, datediff(wk, 2, getdate()) - 2, 6)) THEN 'MA4'
WHEN wadat_ist BETWEEN (select dateadd(wk, datediff(wk, 1, getdate()) - 1, 0)) AND (SELECT EOMONTH(getdate(),-1)) THEN 'MA5'
Using T-SQL
As a one of the solutions you can create TimeTable in your database or temp table with your range of time period and then generate column WeekOfMonth:
1. create table at least with these columns(date, year, month, week, quarter : use DATEPART)
2. generate your column:
WeekOfMonth = DENSE_RANK() OVER (PARTITION BY [year], [month] ORDER BY [week])
If you create a good time table it will be useful for future tasks.
Try below (partial) query, comments are inline:
-- set monday as first day of week
set datefirst 1;
-- after checking, that 1 of september is 35th week of year, you can do the following:
select case when datepart(week, wadat_ist) = 35 then 'MA1'
when datepart(week, wadat_ist) = 36 then 'MA2'
when datepart(week, wadat_ist) = 37 then 'MA3'
when datepart(week, wadat_ist) = 38 then 'MA4'
when datepart(week, wadat_ist) = 39 then 'MA5'
end as 'Activity'
or shorter
select case datepart(week, wadat_ist)
when 35 then 'MA1'
when 36 then 'MA2'
when 37 then 'MA3'
when 38 then 'MA4'
when 39 then 'MA5'
end as 'Activity'
I am almost a newbie to writing SQL queries.
In the context of SQL Server, how to get list of 2nd and 4th Saturday dates
in the year 2016?
Done as a derived table simply to show the logic but you can reduce if you prefer:
select *
from (
select d2016,
datename( weekday, d2016 ) as wkdy,
row_number( ) over ( partition by datepart( month, d2016 ), datename( weekday, d2016 ) order by d2016 ) as rn_dy_mth
from (
select dateadd( day, rn, cast( '2016-01-01' as date ) ) as d2016
from (
select row_number() over( order by object_id ) - 1 as rn
from sys.columns
) as rn
) as dy
) as dy_mth
where rn_dy_mth in ( 2, 4 )
and wkdy = 'Saturday'
order by d2016
--DEFINE LIMITS FOR DAY
DECLARE #TODATE DATETIME, #FROMDATE DATETIME
SET #FROMDATE ='2010-01-01'
SET #TODATE = '2017-12-31'
;WITH DATESEQUENCE( [DATE] ) AS
(
SELECT #FROMDATE AS [DATE]
UNION ALL
SELECT DATEADD(DAY, 1, [DATE])
FROM DATESEQUENCE
WHERE DATE < #TODATE
)
, DATESATURDAY AS
(SELECT CAST(CAST(YEAR([DATE]) AS VARCHAR)+
(CASE WHEN DATEPART(M,[DATE])<=9 THEN '0'+CAST(DATEPART(M,[DATE]) AS VARCHAR)
ELSE CAST(DATEPART(M,[DATE]) AS VARCHAR) END ) AS NUMERIC) AS MONTH_ID
,CONVERT(VARCHAR,[DATE],106) AS DAY_DESC
,UPPER(DATENAME(DW,[DATE]))AS DAY_NAME
FROM DATESEQUENCE )
,SECOND_FOURTH_SATURDAY AS
(SELECT *
,ROW_NUMBER() OVER (PARTITION BY MONTH_ID ORDER BY DAY_NAME) FALL_IN
FROM DATESATURDAY
WHERE DAY_NAME='SATURDAY')
SELECT * FROM SECOND_FOURTH_SATURDAY
WHERE FALL_IN IN(2,4)
OPTION (MAXRECURSION 10000)
You can get any Saturday of a month using the Following Query in SQL.
Here I'm Getting on Current Date, You can set your own selected date to get a Specific month Saturday
select DATEADD(dd, (14 - ##DATEFIRST - DATEPART(dw, DATEADD(MONTH, DATEDIFF(mm, 0,getdate()), 0))) % 7, DATEADD(MONTH, DATEDIFF(mm, 0, getdate()), 0)) as FirstSaturday,
DATEADD(dd,7,DATEADD(dd, (14 - ##DATEFIRST - DATEPART(dw, DATEADD(MONTH, DATEDIFF(mm, 0, getdate()), 0))) % 7, DATEADD(MONTH, DATEDIFF(mm, 0, getdate()), 0))) as SecondSaturday,
DATEADD(dd,14,DATEADD(dd, (14 - ##DATEFIRST - DATEPART(dw, DATEADD(MONTH, DATEDIFF(mm, 0, getdate()), 0))) % 7, DATEADD(MONTH, DATEDIFF(mm, 0, getdate()), 0))) as ThirdSaturday,
DATEADD(dd,21,DATEADD(dd, (14 - ##DATEFIRST - DATEPART(dw, DATEADD(MONTH, DATEDIFF(mm, 0, getdate()), 0))) % 7, DATEADD(MONTH, DATEDIFF(mm, 0, getdate()), 0))) as LastSaturday
How could I get the first business day of the current month?
Without create a function, only select.
something like that:
SELECT CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(GETDATE())-1), GETDATE()), 101)
somebody knows please?
Thanks.
A Simple case statement could do it
SELECT CASE
WHEN DATENAME(WEEKDAY, dateadd(mm, DATEDIFF(MM, 0, getdate()), 0)) = 'Saturday'
THEN dateadd(mm, DATEDIFF(MM, 0, getdate()), 0) + 2
WHEN DATENAME(WEEKDAY, dateadd(mm, DATEDIFF(MM, 0, getdate()), 0)) = 'Sunday'
THEN dateadd(mm, DATEDIFF(MM, 0, getdate()), 0) + 1
ELSE dateadd(mm, DATEDIFF(MM, 0, getdate()), 0)
END
This will literally give you what you're asking for -- the first business day in a month if we define a business day as "any day that's not a Saturday or a Sunday". But this is is a very narrow definition of "business day" that is not appropriate when taking into account holidays and cultural differences, so it generalizes poorly. The typical solution for this problem is to create a table that actually holds the working days (which is generated somewhere just before he year, or calculated in advance if that's feasible), and simply look it up in that.
SELECT DATEADD(DAY,
CASE
(DATEPART(WEEKDAY, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)) + ##DATEFIRST - 1) % 7
WHEN 6 THEN 2
WHEN 7 THEN 1
ELSE 0
END,
DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)
)
This solution uses ##DATEFIRST to avoid any language issues -- using DATEPART(WEEKDAY, ...) on its own or DATENAME() only works if we assume a specific region.
If you have more flexibility in your SELECT statement, you might be able to use something like this:
;With Daterange As
(
Select DateAdd(Month, DateDiff(Month, 0, GetDate()), 0) As Date Union All
Select DateAdd(Day, 1, Date) As Date
From DateRange
Where Date < DateAdd(Day, 6, DateAdd(Month, DateDiff(Month, 0, GetDate()), 0))
)
Select Convert(Date, Min(Date)) FirstBusinessDay
From Daterange
Where DatePart(WeekDay, Date) Not In (7, 1)
Try this.
SELECT CASE
WHEN Datename(dw, Dateadd(dd, -Datepart(dd, Getdate()) + 1, Getdate())) = 'Saturday' THEN Dateadd(dd, -Datepart(dd, Getdate()) + 3, Getdate())
WHEN Datename(dw, Dateadd(dd, -Datepart(dd, Getdate()) + 1, Getdate())) = 'Sunday' THEN Dateadd(dd, -Datepart(dd, Getdate()) + 2, Getdate())
ELSE Dateadd(dd, -Datepart(dd, Getdate()) + 1, Getdate())
END
Explanation :
Find the first day of the month.
Dateadd(dd, -Datepart(dd, Getdate()) + 1, Getdate())
Then check the day of the previous date by using Datename function.
Datename(dw, Dateadd(dd, -Datepart(dd, Getdate()) + 1, Getdate()))
If the Datename is Saturday the add 2 days to the first day of the month . if it is sunday then add 1 day to the first day of the month else get the first day of the month
I have a stored proc that produces a table like this:
PeriodStart PeriodEnd TotalActive TotalAdded TotalRemoved
2011-03-01 2011-03-07 123 456 789
2011-03-08 2011-03-14 567 789 123
2011-03-15 2011-03-21 444 555 666
etc...
I need to display the results in a table that looks like this:
03-01-2011 03-08-2011 03-15-2011
Active 123 567 444
Added 456 789 555
Removed 789 123 666
I've never had to use PIVOT before so I'm a little unsure of how to modify the below SQL in order to achieve the desired result. Here's the sproc:
ALTER PROCEDURE [dbo].[TrendReport]
#DateStart datetime,
#DateEnd datetime,
#Frequency varchar(5)
AS
BEGIN
SELECT
PeriodStart,
PeriodEnd,
SUM(TotalActive) As TotalActive,
SUM(TotalAdded) As TotalAdded,
SUM(TotalRemoved) As TotalRemoved
FROM (
SELECT
PeriodStart = CASE #Frequency
WHEN 'day' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, [Date]))
WHEN 'week' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(DAY, 1 - DATEPART(WEEKDAY, [Date]), [Date])))
WHEN 'month' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(MONTH, DATEDIFF(MONTH, 0, [Date]), 0)))
WHEN 'quarter' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(QUARTER, DATEDIFF(QUARTER, 0, [Date]), 0)))
WHEN 'year' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(YEAR, DATEDIFF(YEAR, 0, [Date]), 0)))
END,
PeriodEnd = CASE #Frequency
WHEN 'day' THEN DATEADD(s, -1, DATEADD(day, 1, DATEDIFF(DAY, 0, [Date])))
WHEN 'week' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, 7 - DATEPART(WEEKDAY, [Date]), [Date]))))
WHEN 'month' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, [Date]) + 1, 0)))))
WHEN 'quarter' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(QUARTER, DATEDIFF(QUARTER, 0, [Date]) + 1, 0)))))
WHEN 'year' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(YEAR, DATEDIFF(YEAR, 0, [Date]) + 1, 0)))))
END,
TotalActive,
TotalAdded,
TotalRemoved
FROM TrendReport P
WHERE [Date] BETWEEN #DateStart AND #DateEnd
) s
GROUP BY
PeriodStart,
PeriodEnd
ORDER BY PeriodStart
END
You actually need to first apply UNPIVOT to rotate the three quantity types from columns to rows and then apply PIVOT to rotate the period start date to columns and aggregate the quantities.
Here's the thing with using the PIVOT operator though, you need to know what columns you will have ahead of time (03-01-2011, 03-08-2011, 03-15-2011), it will need hard coded into the query (unless you want to get down and dirty with dynamic sql, which i would read up on before using in production)
Here is the solution:
WITH CTE AS (
SELECT
PeriodStart,
PeriodEnd,
SUM(TotalActive) As TotalActive,
SUM(TotalAdded) As TotalAdded,
SUM(TotalRemoved) As TotalRemoved
FROM (
SELECT
PeriodStart = CASE #Frequency
WHEN 'day' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, [Date]))
WHEN 'week' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(DAY, 1 - DATEPART(WEEKDAY, [Date]), [Date])))
WHEN 'month' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(MONTH, DATEDIFF(MONTH, 0, [Date]), 0)))
WHEN 'quarter' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(QUARTER, DATEDIFF(QUARTER, 0, [Date]), 0)))
WHEN 'year' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(YEAR, DATEDIFF(YEAR, 0, [Date]), 0)))
END,
PeriodEnd = CASE #Frequency
WHEN 'day' THEN DATEADD(s, -1, DATEADD(day, 1, DATEDIFF(DAY, 0, [Date])))
WHEN 'week' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, 7 - DATEPART(WEEKDAY, [Date]), [Date]))))
WHEN 'month' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, [Date]) + 1, 0)))))
WHEN 'quarter' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(QUARTER, DATEDIFF(QUARTER, 0, [Date]) + 1, 0)))))
WHEN 'year' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(YEAR, DATEDIFF(YEAR, 0, [Date]) + 1, 0)))))
END,
TotalActive,
TotalAdded,
TotalRemoved
FROM TrendReport P
WHERE [Date] BETWEEN #DateStart AND #DateEnd
) s
GROUP BY
PeriodStart,
PeriodEnd
ORDER BY PeriodStart
), U AS (
SELECT qty_type, PeriodStart, qty
FROM CTE
UNPIVOT(qty FOR qty_type IN([TotalActive], [TotalAdded], [TotalRemoved]))Q
)
SELECT * FROM U
PIVOT (SUM(Qty) FOR PeriodStart IN([03/01/2011], [03/08/2011], [03/15/2011])) AS P
I do not have an instance of SQL on my machine at the moment, so this may have some problems with syntax. However, give this a try...it is my attempt at the craftiness via dynamic SQL that J Cooper referred to:
CREATE TABLE #Temp1 (ID INT IDENTITY(1,1), PeriodStart DATETIME, PeriodEnd DATETIME, TotalActive INT, TotalAdded INT, TotalRemoved INT)
INSERT INTO #Temp1 (PeriodStart, PeriodEnd, TotalActive, TotalAdded, TotalRemoved)
SELECT
PeriodStart,
PeriodEnd,
TotalActive,
TotalAdded,
TotalRemoved
FROM (
SELECT
PeriodStart = CASE #Frequency
WHEN 'day' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, [Date]))
WHEN 'week' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(DAY, 1 - DATEPART(WEEKDAY, [Date]), [Date])))
WHEN 'month' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(MONTH, DATEDIFF(MONTH, 0, [Date]), 0)))
WHEN 'quarter' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(QUARTER, DATEDIFF(QUARTER, 0, [Date]), 0)))
WHEN 'year' THEN DATEADD(hour, 0, DATEDIFF(DAY, 0, DATEADD(YEAR, DATEDIFF(YEAR, 0, [Date]), 0)))
END,
PeriodEnd = CASE #Frequency
WHEN 'day' THEN DATEADD(s, -1, DATEADD(day, 1, DATEDIFF(DAY, 0, [Date])))
WHEN 'week' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, 7 - DATEPART(WEEKDAY, [Date]), [Date]))))
WHEN 'month' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, [Date]) + 1, 0)))))
WHEN 'quarter' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(QUARTER, DATEDIFF(QUARTER, 0, [Date]) + 1, 0)))))
WHEN 'year' THEN DATEADD(s, -1, DATEADD(hour, 0, DATEDIFF(DAY, -1, DATEADD(DAY, -1, DATEADD(YEAR, DATEDIFF(YEAR, 0, [Date]) + 1, 0)))))
END,
TotalActive,
TotalAdded,
TotalRemoved
FROM TrendReport P
WHERE [Date] BETWEEN #DateStart AND #DateEnd
) s
GROUP BY
PeriodStart,
PeriodEnd
ORDER BY PeriodStart
DECLARE #CreatePivot VARCHAR(MAX), #PivotColumns VARCHAR(MAX)
SET #CreatePivot = 'CREATE TABLE #Temp2 (BaseColumn VARCHAR(25)'
DECLARE #Count INT, #CurrentDateBeingChecked DATETIME
SET #Count = 1
WHILE(SELECT COUNT(*) FROM #Temp1 WHERE ID >= #Count) > 0
BEGIN
SELECT #CurrentDateBeingChecked = PeriodStart FROM #Temp1 WHERE ID = #Count
IF #Count > 1
SET #PivotColumns = #PivotColumns + ','
SET #PivotColumns = #PivotColumns + '[' + CAST(#CurrentDateBeingChecked AS VARCHAR(15) + ']'
SET #CreatePivot = #CreatePivot + ', [' + CAST(#CurrentDateBeingChecked AS VARCHAR(15) + '] INT'
SET #Count = #Count + 1
END
SET #CreatePivot = #CreatePivot + ')'
sp_executesql(#CreatePivot)
DECLARE #PivotStatementToRun VARCHAR(MAX)
SET #PivotStatementToRun =
'
INSERT INTO #Temp2
SELECT 'Active' AS BaseColumn,
' + #PivotColumns + '
FROM
(SELECT PeriodStart, TotalActive
FROM #Temp1) AS SourceTable
PIVOT
(
SUM(TotalActive)
FOR PeriodStart IN (
' + #PivotColumns + ')
) AS PivotTable;
'
sp_executesql(#PivotStatementToRun)
SET #PivotStatementToRun =
'
INSERT INTO #Temp2
SELECT 'Added' AS BaseColumn,
' + #PivotColumns + '
FROM
(SELECT PeriodStart, TotalAdded
FROM #Temp1) AS SourceTable
PIVOT
(
SUM(TotalAdded)
FOR PeriodStart IN (
' + #PivotColumns + ')
) AS PivotTable;
'
sp_executesql(#PivotStatementToRun)
SET #PivotStatementToRun =
'
INSERT INTO #Temp2
SELECT 'Removed' AS BaseColumn,
' + #PivotColumns + '
FROM
(SELECT PeriodStart, TotalRemoved
FROM #Temp1) AS SourceTable
PIVOT
(
SUM(TotalRemoved)
FOR PeriodStart IN (
' + #PivotColumns + ')
) AS PivotTable;
'
sp_executesql(#PivotStatementToRun)
SELECT * FROM #Temp2
I am trying to list last a website's statistics.
I listed Last 30 days with;
CONVERT(VARCHAR(10), S.DATEENTERED, 101)
BETWEEN
CONVERT(VARCHAR(10), GETDATE()-30, 101)
AND
CONVERT(VARCHAR(10), GETDATE(), 101)
and this month with;
RIGHT(CONVERT(VARCHAR(10), S.DATEENTERED, 103), 7) =
RIGHT(CONVERT(VARCHAR(10), GETDATE(), 103), 7)
but I have no idea what query to use for last month. I tried with;
RIGHT(CONVERT(VARCHAR(10), S.DATEENTERED, 103), 7) =
RIGHT(CONVERT(VARCHAR(10), GETDATE()-1, 103), 7)
Did not work.
Dates are always a joy to work with in any programming language, SQL not excluded.
To answer your question to find all records that occurred last month
select S.DATEENTERED
,*
from sometable S
where S.DATEENTERED
between dateadd(mm, datediff(mm, 0, dateadd(MM, -1, getdate())), 0)
and dateadd(ms, -3, dateadd(mm, datediff(mm, 0, dateadd(MM, -1, getdate())) + 1, 0))
order by 1
To expand the best means for getting records within a certain time-frame is by utilizing the datediff function, dateadd function, and the between condition in the where clause.
select 'howdy'
,getdate()
where getdate()
between dateadd(mm, 0, 0)
and dateadd(ms, -3, dateadd(mm, datediff(mm, 0, dateadd(mm,-1,getutcdate())) + 1, 0))
The above code will result in no records returned because it is checking to see if today's date is between 1900-01-01 00:00:00.000 and the last possible recorded date of last month (the last day and 23:59:59.997 - SQL Server DATETIME columns have at most a 3 millisecond resolution).
The following code will return a record as the date we are searching for is one month ago.
select 'howdy'
,dateadd(mm, -1, getdate())
where dateadd(mm, -1, getdate())
between dateadd(mm, 0, 0)
and dateadd(ms, -3, dateadd(mm, datediff(mm, 0, dateadd(mm,-1,getutcdate())) + 1, 0))
A break down of the where clause:
WHERE getdate() -- date to check
between dateadd(mm, 0, 0) -- begin date
and dateadd(ms, -3, dateadd(mm, datediff(mm, 0, dateadd(mm,-1,getutcdate())) + 1, 0)) -- end date
Finally, a variety of dates can be ascertained in this manner here is a pretty complete list:
select dateadd(mm, 0, 0) as BeginningOfTime
,dateadd(dd, datediff(dd, 0, getdate()), 0) as Today
,dateadd(wk, datediff(wk, 0, getdate()), 0) as ThisWeekStart
,dateadd(mm, datediff(mm, 0, getdate()), 0) as ThisMonthStart
,dateadd(qq, datediff(qq, 0, getdate()), 0) as ThisQuarterStart
,dateadd(yy, datediff(yy, 0, getdate()), 0) as ThisYearStart
,dateadd(dd, datediff(dd, 0, getdate()) + 1, 0) as Tomorrow
,dateadd(wk, datediff(wk, 0, getdate()) + 1, 0) as NextWeekStart
,dateadd(mm, datediff(mm, 0, getdate()) + 1, 0) as NextMonthStart
,dateadd(qq, datediff(qq, 0, getdate()) + 1, 0) as NextQuarterStart
,dateadd(yy, datediff(yy, 0, getdate()) + 1, 0) as NextYearStart
,dateadd(ms, -3, dateadd(dd, datediff(dd, 0, getdate()) + 1, 0)) as TodayEnd
,dateadd(ms, -3, dateadd(wk, datediff(wk, 0, getdate()) + 1, 0)) as ThisWeekEnd
,dateadd(ms, -3, dateadd(mm, datediff(mm, 0, getdate()) + 1, 0)) as ThisMonthEnd
,dateadd(ms, -3, dateadd(qq, datediff(qq, 0, getdate()) + 1, 0)) as ThisQuarterEnd
,dateadd(ms, -3, dateadd(yy, datediff(yy, 0, getdate()) + 1, 0)) as ThisYearEnd
Using the above list a range of any type can be determined.
The following will find you the start of the last month:
-- Start of last month
SELECT CAST('01 '+ RIGHT(CONVERT(CHAR(11),DATEADD(MONTH,-1,GETDATE()),113),8) AS datetime)
You would then find the start of this month, using the following, minus one.
-- Start of the month
SELECT CAST('01 '+ RIGHT(CONVERT(CHAR(11),GETDATE(),113),8) AS datetime)
When I have to work with dates in SQL Server I often reference Robyn Page's SQL Server DATE/TIME Workbench. The workbench (tutorial) is well laid out and contains just about everything I have ever needed when working with dates on SQL Server.
How about this?
select DATEADD(month, -1, GETDATE())
I would suggest using the first day of last month and the first day of the current month for the operation and rather than using BETWEEN use >= and <. That's my personal opinion, but I believe you will find there are performance and maintainability benefits to this approach.
Here's the sql. You will notice I've included the last day of the last month value just in case you end up going with another approach.
Keep in mind, these dates are based off of 12:00AM that day. In other words, getting values between 6/1/2009 and 6/30/2009 won't get you what you want as all of 6/30/2009 is excluded. If you use the first day of July (7/1/2009) you are covered.
Again, I recommend avoiding BETWEEN all together as shown below. Best of luck.
Declare #LastMonthFirstDay datetime
Declare #LastMonthLastDay datetime
Declare #ThisMonthFirstDay datetime
Set #LastMonthFirstDay = DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP) - 1, 0);
Set #ThisMonthFirstDay = DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP), 0);
Set #LastMonthLastDay = DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP), 0));
Select * From Table
Where DateEntered >= #LastMonthFirstDay
And DateEntered < #ThisMonthFirstDay;
Try using the DATEADD function. You can add a -1 with the MONTH (mm) datepart and it should work. Here is a link
where year(S.DATEENTERED) = year(dateadd(mm, -1, getdate())) and month(S.DATEENTERED) = month(dateadd(mm, -1, getdate()))
Might not be good performance-wise but you've got the idea.
GET FIRST DAY OF LAST MONTH
SELECT DATEADD(MM, DATEDIFF(MM, '01/01/2000', DATEADD(MM, -1,GETDATE())), '01/01/2000')
GET LAST DAY OF LAST MONTH
SELECT DATEADD(SS,-1,DATEADD(MM, DATEDIFF(MM,'01/01/2000',GETDATE()),'01/01/2000'))
Then search based on this range.
Try:
declare #lastm int
set #lastm = datepart(mm,getdate()) - 1
...
where datepart(mm,s.dateentered) = #lastm