TSQL - char changing to INT - sql

I need the variable #end_period be character e.g. 01 and not 1
What is wrong with the following code?
DECLARE #start_year AS CHAR(4)
DECLARE #end_year AS CHAR(4)
DECLARE #start_period AS CHAR(2)
DECLARE #end_period AS CHAR(2)
DECLARE #start_date as datetime
DECLARE #end_date as datetime
SET #start_year = '2014'
SET #end_year = '2014'
SET #start_period = '07'
SET #end_period = '08'
SET #end_year = CASE WHEN #end_period ='12' THEN #end_year + 1 ELSE #end_year END
SET #end_period = CASE WHEN #end_period ='12' THEN '01' ELSE #end_period + 1 END
select #end_year
select #end_period

There's something weird about using CHAR. I don't know why but when I do this, I get your desired results:
DECLARE #start_year AS CHAR(4)
DECLARE #end_year AS CHAR(4)
DECLARE #start_period AS CHAR(2)
DECLARE #end_period AS CHAR(2)
DECLARE #start_date as datetime
DECLARE #end_date as datetime
SET #start_year = '2014'
SET #end_year = '2014'
SET #start_period = '07'
SET #end_period = '08'
SET #end_year = CASE WHEN #end_period ='12' THEN #end_year + 1 ELSE #end_year END
SET #end_period = CASE WHEN #end_period ='12' THEN '01' ELSE RIGHT('0'+CAST((#end_period + 1) AS varchar(2)) ,2) END
select #end_year
select #end_period
However when I change this: CAST((#end_period + 1) AS varchar(2))
To this: CAST((#end_period + 1) AS char(2))
I just get a '9' instead of '09'. Weird. I don't know why.
EDIT: MYSTERY SOLVED.
I don't know why I didn't think of this right away. Actually, I do. It's only 9 am.
The '9' that you are seeing as a result is actually '9 ' (9 with a blank space after it) because char(2) has to have 2 characters in it. So doing RIGHT('0'+'9 ') is of course going to return '9 '. You could use RTRIM() or REPLACE() to get rid of the space while preceding it with a zero if you want, or you can just use the varchar cast I illustrated above.

When you do :
#end_period + 1
Example :
'08'+1
The string '08' is converted to the integer 8, one is added, result => 9.
An implicit conversion is then made back to char(2), which is '9'.
The full matrix of possible conversions (implicit or explicit) can be found on MSDN.
To solve your problem, you can then add leading zeroes this way :
SET #end_period = CASE WHEN #end_period ='12' THEN '01' ELSE RIGHT('00' + CAST((#end_period + 1) as VARCHAR(2)), 2) END

Try
SET #end_period = CASE WHEN #end_period = '12' THEN '01'
ELSE CASE WHEN #end_period > 8 THEN CONVERT(VARCHAR,#end_period + 1)
ELSE '0' + CONVERT(VARCHAR,#end_period + 1)
END
END

Related

MSSQL Date Format

i want to get sql date format as follow
this is i tried code
select case when
left(datepart(day,getdate()),1)=4 then concat(datepart(day,getdate()),'th',' of ',DATENAME(month,GETDATE()),' ',datepart(year,getdate()))
end
this is output from my query 4th of August 2020
DECLARE #day int = datepart(day,getdate())
SELECT CONCAT(#day,
CASE WHEN #day=1 OR #day=21 OR #day=31 THEN 'st'
WHEN #day=2 OR #day=22 THEN 'nd'
WHEN #day=3 OR #day=23 THEN 'rd' ELSE 'th' END, ' of ',DATENAME(month,GETDATE()),' ',datepart(year,getdate()) )AS 'Date'
Would give you something like that.
Edit : if you make it as function, and pass it date as param you could use that pretty much anywhere. Will need to replace getdate() with parameter name then
CREATE FUNCTION [dbo].[fnc_GetDateString]
(
#date DATETIME
)
RETURNS nvarchar(100)
AS
BEGIN
--DECLARE #date DATETIME = '2020-08-31'
DECLARE #day int = datepart(day,#date)
DECLARE #DateString nvarchar(100)
SET #DateString = CONCAT(#day,
CASE WHEN #day=1 OR #day=21 OR #day=31 THEN 'st'
WHEN #day=2 OR #day=22 THEN 'nd'
WHEN #day=3 OR #day=23 THEN 'rd' ELSE 'th' END, ' of ',DATENAME(month,#date),' ',datepart(year,#date) )
RETURN #DateString
END

SQL Replace and Update a Datetime string "before a certain date"

I have a data field Date in the format of yyyyMMdd string (varchar). How do I replace everything before a certain date, say 20180201, to certain month, say March 2018!? Only the year and the month are changed, keep the day.
Example: A string 20160913 will be changed to 20180313, but 20180224 will be kept as it was, because it was after 20180201.
Convert that string to a date to search for the greater than a date, and use substring to extract the day part to build the new date string.
declare #NewYear varchar(4) = '2018'
declare #NewMonth varchar(2) = '03'
declare #PivotDate date = '2018-02-01'
update myTable set MyField = #NewYear + #NewMonth + substring(MyField, 6, 2)
where convert(date, MyField, 112) > #PivotDate
I would recommend doing this as:
declare #NewYear varchar(4) = '2018';
declare #NewMonth varchar(2) = '03';
declare #PivotDate date = '2018-02-01';
update myTable
set MyField = #NewYear + #NewMonth + right(MyField, 2)
where myfield < convert(varchar(255), #PivotDate, 112);
The important part of this solution is the where clause. In particular, there is no function call on myfield which allows an index to be used. An expression that allows an index is called sargable.
I would recommend to doing this, because if #NewMonth < February, then it can be a problem.
declare #NewYear varchar(4) = '2018'
declare #NewMonth varchar(2) = '02'
declare #PivotDate date = '2018-02-01'
update myTable set MyField = DATEADD(day,(right(MyField, 2)-1),cast((#NewYear + #NewMonth + '01') as date))
where convert(date, MyField, 112) > #PivotDate
Thank You!

Sql Datetime convert

In a database table, I have two column storing date and time in this format:
D30DAT D30TIM
140224 75700
I need update a new field where store date in the format
2014-02-24 07:57:00.000
How I can use a SQL query to do it?
For Postgres and Oracle (assuming those columns are varchar):
select to_timestamp(dt, 'yymmdd hh24miss')
from (
select d30dat||' '||case when length(d30tim) = 5 then '0'||d30tim else d30tim end as dt
from x
) t;
The case expression adds a leading 0 if the time part only consists of 5 digits so that the format mask can be specified with always 2 digits for the hour. The blank between the two columns is essentially only a debugging aid and could be left out.
The result is a real timestamp value that can easily be formatted using to_char() to the desired format.
SQLFiddle for Postgres: http://sqlfiddle.com/#!15/ac07a/2
SQLFiddle for Oracle: http://sqlfiddle.com/#!4/ac07a2/4
Try this function. Its not particularly fast or great, but converts the fields you specified.
CREATE FUNCTION GetDateTimeFromINT
(
#Date INT,
#Time INT
)
RETURNS DATETIME
AS
BEGIN
DECLARE #YearNo VARCHAR(4)
DECLARE #MonthNo VARCHAR(3)
DECLARE #DayNo VARCHAR(2)
DECLARE #HourNo VARCHAR(2)
DECLARE #MinNo VARCHAR(2)
DECLARE #SecNo VARCHAR(2)
SET #YearNo = LEFT(CONVERT(VARCHAR,#Date), LEN(#Date)-4)
SET #MonthNo = SUBSTRING(CONVERT(VARCHAR,#Date),LEN(#Date)-3,2)
SET #DayNo = SUBSTRING(CONVERT(VARCHAR,#Date),LEN(#Date)-1,2)
SET #HourNo = LEFT(CONVERT(VARCHAR,#Time), LEN(#Time)-4)
SET #MinNo = SUBSTRING(CONVERT(VARCHAR,#Time),LEN(#Time)-3,2)
SET #SecNo = SUBSTRING(CONVERT(VARCHAR,#Time),LEN(#Time)-1,2)
SET #YearNo = '20' + #YearNo
IF LEN(#HourNo) = 1
BEGIN
SET #HourNo = '0' + #HourNo
END
SET #MonthNo = CASE
WHEN #MonthNo = '01' THEN 'JAN'
WHEN #MonthNo = '02' THEN 'FEB'
WHEN #MonthNo = '03' THEN 'MAR'
WHEN #MonthNo = '04' THEN 'APR'
WHEN #MonthNo = '05' THEN 'MAY'
WHEN #MonthNo = '06' THEN 'JUN'
WHEN #MonthNo = '07' THEN 'JUL'
WHEN #MonthNo = '08' THEN 'AUG'
WHEN #MonthNo = '09' THEN 'SEP'
WHEN #MonthNo = '10' THEN 'OCT'
WHEN #MonthNo = '11' THEN 'NOV'
WHEN #MonthNo = '12' THEN 'DEC'
END
RETURN CONVERT(DATETIME, #DayNo + '-' + #MonthNo + '-' + #YearNo +' ' + #HourNo + ':' + #MinNo + ':' + #SecNo)
END
GO
Call it like so:
SELECT *, dbo.GetDateTimeFromINT(D30DAT,T30DAT) OutputDT
FROM SourceTable
If you need help with the update statement, let me know
Because someone gave a convoluted answer in SQL Server, I want to point out that there is a much simpler way.
I also want to point out that the format is not unreasonable. It provides easy access to the date parts and it is sortable. Of course, a real date/time value has these properties as well; I am guessing that this is some legacy format from some ancient system.
In any case, try this:
with t as (select 140224 as ymd, 75700 as hms)
select cast(cast(ymd as varchar(255)) + ' ' +
stuff(stuff(right('000000' + cast(hms as varchar(255)), 6
), 3, 0, ':'
), 6, 0, ':')
from t;
This turns the numbers into the format YYMMDD HH:MM:SS which SQL Server recognizes as a date/time value. Actually it would be better to pre-pend "20" for the four-digit year, but I'm not sure what the OP wants in terms of Y2K convertibility.
Although the code would look a bit different, similar logic would work in most databases.

How to find the Nearest (day of the week) for a given date

I been practicing queries, and my current scenario is to find the nearest Saturday for a given date. After i got the logic down, i came up with a, whats looks like a long and messy query. And I was wondering if there is a way to simplify this.
Here's my query
DECLARE #DATE DATE
SET #DATE ='2013-09-13'
IF DATENAME(DW,#DATE) = 'SUNDAY'
BEGIN
SELECT DATEADD(DAY,-1,#DATE) AS DATE, 'IS THE NEAREST SATURDAY'
END
ELSE IF DATENAME(DW,#DATE) = 'MONDAY'
BEGIN
SELECT DATEADD(DAY,-2,#DATE) AS DATE, 'IS THE NEAREST SATURDAY'
END
ELSE IF DATENAME(DW,#DATE) = 'TUESDAY'
BEGIN
SELECT DATEADD(DAY,-3,#DATE) AS DATE, 'IS THE NEAREST SATURDAY'
END
ELSE IF DATENAME(DW,#DATE) = 'WEDNESDAY'
BEGIN
SELECT DATEADD(DAY,3,#DATE) AS DATE, 'IS THE NEAREST SATURDAY'
END
ELSE IF DATENAME(DW,#DATE) = 'THURSDAY'
BEGIN
SELECT DATEADD(DAY,2,#DATE) AS DATE, 'IS THE NEAREST SATURDAY'
END
ELSE IF DATENAME(DW,#DATE) = 'FRIDAY'
BEGIN
SELECT DATEADD(DAY,1,#DATE) AS DATE, 'IS THE NEAREST SATURDAY'
END
ELSE IF DATENAME(DW,#DATE) = 'SATURDAY'
BEGIN
SELECT CONVERT(NVARCHAR,#DATE) + ' IS SATURDAY' AS DATE_DOW
END
As we can see the query is long and runs multiple IFs to look for TRUE condition.
Please don't write the query, just hints. I would like to work on the query myself.
Here's my hint without answering, as you requested:
Consider date manipulation, using current date (you can use GETDATE() or your date variable), DATEADD() and DATEDIFF() can be used to write this in a couple lines.
If you just want to simplify your method you could use a CASE statement:
DECLARE #date DATE = '2013-09-13'
SELECT CASE WHEN DATENAME(DW,#DATE) = 'SUNDAY' THEN CAST(DATEADD(DAY,-3,#DATE) AS VARCHAR(12)) + ' IS THE NEAREST SATURDAY'
WHEN DATENAME(DW,#DATE) = 'MONDAY' THEN CAST(DATEADD(DAY,-2,#DATE) AS VARCHAR(12)) + ' IS THE NEAREST SATURDAY'
WHEN DATENAME(DW,#DATE) = 'TUESDAY' THEN CAST(DATEADD(DAY,-1,#DATE) AS VARCHAR(12)) + ' IS THE NEAREST SATURDAY'
WHEN DATENAME(DW,#DATE) = 'WEDNESDAY' THEN CAST(DATEADD(DAY,1,#DATE) AS VARCHAR(12)) + ' IS THE NEAREST SATURDAY'
WHEN DATENAME(DW,#DATE) = 'THURSDAY' THEN CAST(DATEADD(DAY,2,#DATE) AS VARCHAR(12)) + ' IS THE NEAREST SATURDAY'
WHEN DATENAME(DW,#DATE) = 'FRIDAY' THEN CAST(DATEADD(DAY,3,#DATE) AS VARCHAR(12)) + ' IS THE NEAREST SATURDAY'
ELSE CONVERT(NVARCHAR,#DATE) + ' IS SATURDAY'
END
To clarify on the method I was hinting at and Sparky posted, you need to adjust DATEFIRST to make this work, it works for whichever day is the first day of the week, Saturday is the 7th day of the week, so:
SET DATEFIRST 7
DECLARE #date DATE = '2013-09-21'
SELECT DATEADD(day,7-DATEPART(weekday,#date),#date)
Well not exactly an answer, but an alternative
DECLARE #DATE DATE,
#SUN DATE,
#MON DATE,
#TUE DATE,
#WED DATE,
#THU DATE,
#FRI DATE,
#SAT DATE
SET #DATE = '2013-09-14'
SET #SUN = DATEADD(DAY,-1,#DATE)
SET #MON = DATEADD(DAY,-1,#DATE)
SET #TUE = DATEADD(DAY,-2,#DATE)
SET #WED = DATEADD(DAY,-3,#DATE)
SET #THU = DATEADD(DAY,2,#DATE)
SET #FRI = DATEADD(DAY,1,#DATE)
SET #SAT = DATEADD(DAY,0,#DATE)
SELECT CASE
WHEN DATENAME(DW,#DATE) = 'SUNDAY'
THEN #SUN
WHEN DATENAME(DW,#DATE) = 'MONDAY'
THEN #MON
WHEN DATENAME(DW,#DATE) = 'TUESDAY'
THEN #TUE
WHEN DATENAME(DW,#DATE) = 'WEDNESDAY'
THEN #WED
WHEN DATENAME(DW,#DATE) = 'THURSDAY'
THEN #THU
WHEN DATENAME(DW,#DATE) = 'FRIDAY'
THEN #FRI
ELSE #SAT
END
Try this:
select dateAdd(dd,7-DATEPART(dw,getDate()),GETDATE())
datePart(dw,...) returns day of the week for current date.
7 - that number, returns number of days until Saturday
Add the result to the date to get the next Saturday...
Similar logic if you need to go back to previous Saturday
Sql Fiddle: http://www.sqlfiddle.com/#!3/61998/2

Date calculation in variable

I'm doing my best to set a date variable so I can compare it later. I would like something that basically says:
If the current day-of-month is less than 11, then date is 10th of LAST month
If the current day-of-month is greater-than-or-equal-to 11, then date is 10th of THIS month
Date is 11/6/2012 expected output:
#PODate = 10/10/2012
Date is 11/16/2012 expected output:
#PODate = 11/10/2012
Currently all I have is this:
DECLARE #PODate as DATETIME
Set #PODate = Convert(varchar(8),GetDate(),1)
Any tips or help would be greatly appreciated. Thank you!!
Trying to keep it as straightforward as possible:
declare #PODate datetime
select #PODate = DATEADD(month,
DATEDIFF(month,'20010110',CURRENT_TIMESTAMP) +
CASE WHEN DATEPART(day,CURRENT_TIMESTAMP) <= 10 THEN -1 ELSE 0 END,
'20010110')
The surrounding DATEADD/DATEDIFF pair are being used to normalize the date to the 10th of the current month. We then use a small CASE expression to subtract a month if the day is less than or equal to the 10th.
Whatever solution you pick, please try to avoid ones that do it as string manipulation. The usual cause of datetime related bugs in SQL is when people treat dates as strings. Keeping the data types appropriately is usually the best way to prevent these issues.
There are, admittedly, 2 strings in my solution, but these are fixed constant strings (all that matters is that they're both for the same year and month, and the second one is for the 10th of the month) and are in an unambiguous format.
Try this: SQL Fiddle
DECLARE
#PODate as DATETIME,
#LastMonth as DateTime,
#strDate as Varchar(50)
set #PODate = '11/16/2012'
set #LastMonth = DATEADD(MONTH, -1, #PODate)
if(DAY(#PODate) < 11)
SET #strDate = CAST(MONTH(#LastMonth) AS VARCHAR)+'/10/'+CAST(YEAR(#LastMonth) AS VARCHAR)
else
SET #strDate = CAST(MONTH(#PODate) AS VARCHAR)+'/10/'+CAST(YEAR(#PODate) AS VARCHAR)
Select CAST(#strDate AS DateTime)
DECLARE #PODate date = '20121116'
SELECT CASE WHEN DATEPART(day, #PODate) < 11 THEN DATEADD(mm, DATEPART(mm, GETDATE()) - DATEPART(mm, #PODate) - 1, DATEADD(day, 10 - DATEPART(day, #PODate), #PODate))
ELSE DATEADD(mm, DATEPART(mm, GETDATE()) - DATEPART(mm, #PODate), DATEADD(day, 10 - DATEPART(day, #PODate), #PODate)) END
Demo on SQLFiddle
DECLARE #currDate DATE = dbo.GetDate()
DECLARE #day INT = day(#currDate)
DECLARE #month INT
DECLARE #year INT
DECLARE #PODate DATE
IF( #day >= 11)
BEGIN
SET #month = month(#currDate)
SET #year = year(#currDate)
END
ELSE BEGIN
SET #month = month(dateadd(m,-1,#currDate))
SET #year = year(dateadd(m,-1,#currDate))
END
SET #PODate = convert(DATE,'10-' + convert(VARCHAR,#month) + '-' + convert(VARCHAR,#year))
PRINT #PODate
if #currDate = '11-jan-2013' , #PODate will be '10-jan-2013', and if #currDate = '07-jan-2013' , #PODate will be '10-Dec-2012'