get last day of previous year from sybase ase - sybase

I need to set a where condition to the last date of previous year.
I looking for the solution using dateadd function but i can not figure it out. This code gives me the last day of current month. But how to get the last day of december last year '2015-12-31' of have tried different ways but it all gives me odd results.
declare #today datetime
select #today=getdate()
select convert(varchar(10), dateadd(dd, -day(dateadd(mm, 1, #today)),dateadd(mm, 1, #today)),101)

Assuming Sybase ASE, not ASA or IQ:
declare #lastyear smallint, #dec31 datetime
select #lastyear = datepart(year,getdate()) - 1
select #dec31 = convert(datetime, convert(char(4), #lastyear) + "1231")
select #dec31
This produces
--------------------------
Dec 31 2015 12:00AM
#lastyear contains 2015, the last year, then text "2015" is concatenaded into "20151231", which is the desired date in AAAAMMDD char format. Next step converts it into date, datetime or smalldatetime. #dec31 stores that result.

select convert(datetime, convert(varchar, datepart(year, getdate()) - 1 ) + '/12' + '/31')
Dec 31 2015 12:00AM

SELECT DATEADD(DD,-1,DATEADD(YEAR, DATEDIFF(YEAR, '', GETDATE())+1, ''))

Related

Week start date and week end date calculated wrong

I have a query for calculating first and last date in the week, according to given date. It is enough to set #dDate and the query will calculate first (monday) and last date (sunday) for that week.
Problem is, that is calculating wrong and I don't understand why.
Example:
#dDate = 2019-10-03 (year-month-day).
Result:
W_START W_END
2019-09-25 2019-10-01
But it should be:
2019-09-30 2019-10-06
Why is that?
Query:
set datefirst 1
declare #dDate date = cast('2019-10-16' as date)
select #dDAte
declare #year int = (select DATEPART(year, #dDAte))
select #year
declare #StartingDate date = cast(('' + cast(#year as nvarchar(4)) + '-01-01') as date)
select #StartingDate
declare #dateWeekEnd date = (select DATEADD(week, (datepart(week, cast(#dDate as date)) - 1), #StartingDate))
declare #dateWeekStart date = dateadd(day, -6, #dateWeekEnd)
select #dateWeekStart W_START, #dateWeekEnd W_END
Days of the week are so complicated. I find it easier to remember that 2001-01-01 fell on a Monday.
Then, the following date arithmetic does what you want:
select dateadd(day,
7 * (datediff(day, '2001-01-01', #dDate) / 7),
'2001-01-01' -- 2001-01-01 fell on a Monday
)
I admit this is something of a cop-out/hack. But SQL Server -- and other databases -- make such date arithmetic so cumbersome that simple tricks like this are handy to keep in mind.

Select records created in a 24 hour time-frame

I'm trying to query our database to find all records that were created between 6am yesterday and 6am today. This will be run in a report at any point during the day so set times/dates are useless.
I have this so far:-
SELECT * FROM DaySummaryDetail DSD
WHERE DSD.FromDateTime BETWEEN DATEADD(DAY, -1, GetDate())
AND DATEADD(Day, 1, GetDate())
But obviously this only works for 24 hours ago from right now until right now. I can't figure out how to apply a time as well as date.
Every example I find online seems slightly different and uses set dates/times ie, >= 20/02/2015 06:00:00.
I normally use Oracle SQL which would simply work using this:-
ptt.mod_date_time >= TRUNC (SYSDATE - 1) - 2 / 24
AND ptt.mod_date_time <= TRUNC (SYSDATE - 1) + 22 / 24
This would return results from 10pm to 10pm but the format appears totally different in SQL Server.
You can get the datetime values you are after by doing the following:
SELECT DATEADD(HOUR,6,CONVERT(DATETIME, CONVERT(DATE ,GETDATE()))) Today6AM,
DATEADD(HOUR,-18,CONVERT(DATETIME, CONVERT(DATE ,GETDATE()))) Yesterday6AM
By doing this: CONVERT(DATE ,GETDATE()) you are stripping off the time portion of today's date. Converting it back to datetime gives you midnight for today.
The query adds 6 hours to midnight of the current day for 6am today and subtracts 18 hours from midnight of the current day to give you 6am on the previous day.
Output:
Today6AM Yesterday6AM
================================================
2015-02-20 06:00:00.000 2015-02-19 06:00:00.000
So adding that to your query:
SELECT *
FROM DaySummaryDetail DSD
WHERE DSD.FromDateTime
BETWEEN DATEADD(HOUR,-18,CONVERT(DATETIME, CONVERT(DATE ,GETDATE())))
AND DATEADD(HOUR,6,CONVERT(DATETIME, CONVERT(DATE ,GETDATE())))
DECLARE #StartTimestamp datetime
DECLARE #EndTimestamp datetime
DECLARE #HourPartOfSearchRange nvarchar(6)
SET #HourPartOfSearchRange = ' 06:30'
SET #StartTimestamp =
CAST((CONVERT(varchar(11), DATEADD(DAY,-1,#CurrentUTCDateTime), 106) + #HourPartOfSearchRange) AS datetime)
SET #EndTimestamp =
CAST((CONVERT(varchar(11), #CurrentUTCDateTime, 106) + #HourPartOfSearchRange) AS datetime)
SELECT * FROM dbo.Test Where Timestamp Between #StartTimestamp AND #EndTimestamp
today 6am is
dateadd(hour,6,cast(cast(getdate() as date) as datetime))
cast(getdate() as date) truncates the timepart, cast it back as datetime because dateadd won't add hours otherwise and add 6hours
One solution would be like so:
select *
from DaySummaryDetail DSD
where DSD.FromDateTime between cast(cast(cast(getdate()-1 as date) as varchar(30)) + ' 06:00:00.000' as datetime)
and cast(cast(cast(getdate() as date) as varchar(30)) + ' 06:00:00.000' as datetime)
This should help ...
SELECT DATEADD( hour, 6, CAST(CAST(GETDATE(), AS Date) AS DateTime) ) AS 'Today#6am'
SELECT DATEADD( hour, 6, CAST(CAST(GETDATE()-1, AS Date) AS DateTime) ) AS 'Yesterday#6am'
In SQL Server 2012 you can use SMALLDATETIMEFROMPARTS to construct a datetime value that is today at 6am like this:
SMALLDATETIMEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), DAY(GETDATE()), 6, 0)
Output: 2015-02-20 06:00:00
then you can use the above expression in place of GETDATE() in the WHERE clause:
DECLARE #TodayAt6AM DATETIME = SMALLDATETIMEFROMPARTS(YEAR(GETDATE()),
MONTH(GETDATE()),
DAY(GETDATE()),
6,
0)
SELECT *
FROM DaySummaryDetail DSD
WHERE DSD.FromDateTime BETWEEN DATEADD(DAY, -1, #TodayAt6AM) AND
DATEADD(Day, 1, #TodayAt6AM)

TSQL Logic in SSRS

I am building a report which has the header field as PropertyStatementForHalfyear Ending :<Date>
So in the DATE field I need to put either May 28 or Nov 28 depending on the date the report Runs
Whats The logic I need to write ??
For example if I run the report today i.e. June 22, I need to display PropertyStatementForHalfyear Ending : 28 Nov 2013
if I run it in December 2013, I need to display PropertyStatementForHalfyear Ending : 28 May 2014
You could use something like this:
DECLARE #DateThreshold1 DATE = '20130528'
DECLARE #DateThreshold2 DATE = '20131128'
DECLARE #CurrentDate DATE = '20131201'
IF #CurrentDate > #DateThreshold2
SELECT CONVERT(VARCHAR(50), DATEADD(YEAR, 1, #DateThreshold1), 106)
ELSE IF #CurrentDate > #DateThreshold1
SELECT CONVERT(VARCHAR(50), #DateThreshold2, 106)
ELSE
SELECT CONVERT(VARCHAR(50), #DateThreshold1, 106)
For dates from 20130101 through 20130528, this will return 28 May 2013
For dates from 20130529 through 20131128, this will return 28 Nov 2013
For dates past 20131128, this will return 28 May 2014
You can easily package this up into a function or a SSRS code snippet
If you're not into IF/CASE statements, like me:
with dt as
(select CAST('2013-11-28' as datetime) dt) --dt becomes your datetime column.
, ymdt as (select
DATEPART(year, dt) y,
DATEPART(month, dt) m,
DATEPART(day, dt) d,
dt
from dt) --split into year, month and date for readability
select y, m, d, dt,
DATEADD(month, 5 + d/28 - (m + d/28) % 6, --add months depending on month and day
DATEADD(day, 28 - d --go to the correct day
, dt) --start calculation from dt (the sql date functions' parameter order has always baffled me)
) HalfYearEndDate
from ymdt
The SQL engine merges all of this into one big fat constant scan or scalar expression on your datetime column.
You should create a SQL or VB function for this if you need this in other reports and also so it doesn't clutter up your queries.
Also: Don't do text formatting in T-SQL unless absolutely necessary! Return a datetime column and do it in the report itself. The format you need to set on the textbox is "dd MMM yyyy" (without the quotes when using the designer).

How to select the beginning of the following April in SQL Server?

Could you please help me select a date which is the beginning of a particular following month, e.g. April?
For example, if it is Jan 08 2013, it should select April 01 2013, but if it is June 08 2013, it should select April 01 2014.
Thanks.
I would create a calendar table, then you can simply do something like this:
select
min([Date])
from
dbo.Calendar
where
MonthNumber = 4 and
DayNumber = 1 and
[Date] > getdate()
Querying a calendar table is usually clearer, simpler and more flexible than using date functions. You might also want to consider what happens if today is April 1: do you want today's date, or next year's?
If you're interested in April 1 because it's the start of a financial year, you can add that information to your calendar table directly:
select
min([Date])
from
dbo.Calendar
where
IsStartOfFinancialYear = 0x1 and
[Date] > getdate()
Use the DATEADD and the DATEPART function, like this short example:
DECLARE #Date Datetime
SET #Date = '2013.01.08 00:00:00'
SELECT DATEADD(year,
CASE WHEN DATEPART(month, #Date) < 4
THEN 0
ELSE 1 END,
DATEADD(day, -DATEPART(day, #Date) + 1,
DATEADD(month, -DATEPART(month, #Date) + 4, #Date)))

SQL Server partitioning monthly data by weeks and calculating weekly weighted average based on month days of that week belong to

I have a table like this:
Month Value
2012-08-01 0.345
2012-09-01 0.543
2012-10-01 0.321
2012-11-01 0.234
2012-12-01 0.234
User inputs week range from '2012-09-29' to '2012-10-13'
Output should show results for all weeks in requested range and average values for each week with the following logic:
- if all weekdays are entirely in one month, just use monthly value for that month
- if weekdays are spread out over two months, calculate weekly value as average between those two months giving preference to the month that contains the most days of that week.
If someone can give me an idea how to do something like this in T-SQL that would be highly appreciated.
The last query is the example. The Calendar table is built on-request, but every database can do with a persisted Calendar table, on which you would filter the date range instead.
declare #tbl table (
Month datetime,
Value decimal(10,3));
insert #tbl select
'2012-08-01', 0.345 union all select
'2012-09-01', 0.543 union all select
'2012-10-01', 0.321 union all select
'2012-11-01', 0.234 union all select
'2012-12-01', 0.234;
declare #start datetime, #end datetime;
select #start = '2012-09-29', #end ='2012-10-13';
;with Calendar(TheDate,StartOfWeek,StartOfMonth) as(
select #start, #start+1-Datepart(dw,#start), #start-Day(#start)+1
union all
select TheDate+1, TheDate+1+1-Datepart(dw,TheDate+1),
TheDate+1-Day(TheDate+1)+1
from Calendar
where TheDate < #end
)
select case when #start > v.StartOfWeek
then #start else v.StartOfWeek end RangeStart,
case when #end < v.StartOfWeek+6
then #end else v.StartOfWeek+6 end RangeEnd,
cast(avg(m.value) as decimal(10,3)) [Average]
from Calendar v
join #tbl m on v.StartOfMonth = m.Month
group by v.StartOfWeek;
Output
RANGESTART RANGEEND Average
September, 29 2012 September, 29 2012 0.543
September, 30 2012 October, 06 2012 0.353
October, 07 2012 October, 13 2012 0.321
Your query would be something like this. The idea is find the first day of the next month DATEADD(mm, DATEDIFF(mm, 0, Month) + 1, 0. Calculate the number of days, and then you can get the monthly total, and calculate the average based on the difference between the first day of the current month and next month. (SQL syntax may need some clean up).
declare #startdate datetime
declare #enddate datetime
set #startdate = '2012-09-05'
set #enddate ='2012-10-13'
Select Monthtotal/DateDiff(d,Month,NextMonth)
FROM
(Select
Month, DATEADD(mm, DATEDIFF(mm, 0, Month) + 1, 0) NextMonth,
DateDiff(d,Month, DATEADD(mm, DATEDIFF(mm, 0, Month) + 1, 0) * Value as Monthtotal
FROM DatesTable
WHERE
#startdate >= Month and
#enddate <= DATEADD(mm, DATEDIFF(mm, 0, Month) + 1, 0))

Resources