I need help with the following query. I want to put a condition on the returned value of select command which is an integer between 0 and any number.
DECLARE #month varchar(50);
set #month ='01-03-05-07-09-11'; <--- clarification: these are all months
Declare #cur_month int;
set #cur_month = Month(GetDate());
select charindex(str(#cur_month), #month);
I essentially want
If ( select charindex(str(#cur_month), #month))
// successful
I get error
An expression of non-boolean type specified in a context where a
condition is expected, near 'print'.
I tried CAST and CONVERT but to no Avail. As you can see, I am trying to see if the current month is in my #month field, I want to execute certain actions if it is.
Taking the answer from #PaulStock with a couple tweaks will work better.
Changes from PaulStock's answer
Left pad for leading zeros. 2 != 02 and wouldn't match.
Add hyphens at the beginning and end of the string so each value is in the form -XX- I included this in case you realize you won't be having the leading zeros. If you'll always have leading zeros you won't need this.
Actual code
DECLARE #month VARCHAR(50);
set #month ='03-05-12-09';
set #month = '-' + #month + '-'
IF CHARINDEX('-' + right('00' + CAST(MONTH('2/13/2011') AS VARCHAR), 2) + '-', #month) > 0
PRINT 'exists'
ELSE
PRINT 'does not exist'
I don't know what variation on the SQL language you are using, since SQL does not support variables and IF statements, but why not use a variable to represent the result of the condition?
SELECT #MyResult=charindex(str(#cur_month), #month);
-- Now you can write an IF statement using the variable
IF #MyResult...
The return value for select charindex is an integer, not a boolean type. You'll need to put a boolean into your if statement.
Try something like:
If ( select charindex(str(#cur_month), #month) > 0)
Instead of using string functions, use date functions since you are trying to compare one datefield to another. And use datetime for #month instead of varchar:
DECLARE #month datetime;
set #month ='09-03-05';
IF MONTH(#month) = MONTH(CURRENT_TIMESTAMP)
PRINT 'Same Month'
UPDATE
Based on your updated question, here is new code:
DECLARE #month VARCHAR(50);
set #month ='03-05-02-09';
IF CHARINDEX(CAST(MONTH(CURRENT_TIMESTAMP) AS VARCHAR), #month) > 0
PRINT 'Same Month'
This solution pads a zero to the left for months < 10, to make sure it works for February (2) when december is on the list (12), as it was pointed out by OCary
DECLARE #month varchar(50);
set #month ='01-05-07-09-11-12';
If (charindex(right('0' + CAST(MONTH(getdate()) as varchar), 2), #month) > 0)
PRINT 'Same Month'
if you run this:
select right('0' + CAST(MONTH(getdate()) as varchar), 2)
it returns 09
Related
EDIT: Forced to use 2008 R2
I need to get the two digit year to appended to an invoice number (for simplicity sake I am using a test variable). Previously I only needed the month and day appended but the customer is now asking for the two digit year.
My Method: REPLACE + SUBSTRING + STR + YEAR(variable DATETIME)
REPLACE((SUBSTRING(STR (Year(#Date),4),3,2)), ' ', '0')**
My code:
DECLARE #TestVariable AS VARCHAR(100),
#Date as datetime = GetDate()
SET #TestVariable = '1234'
+ REPLACE(STR(MONTH(#Date), 2), ' ', '0')
+ REPLACE(STR(DAY(#Date), 2), ' ', '0')
+ REPLACE((SUBSTRING(STR (Year(#Date),4),3,2)), ' ', '0')
PRINT #TestVariable
Honestly, just don't work with 2 digit years any more; learn the lessons of last century's mistake and use 4 digits.
If you "have" to, then you could use CONVERT with a style code, and then just replace the characters with an empty string:
DECLARE #TestVariable varchar(100) = '1234',
#Date datetime = GETDATE();
SELECT #TestVariable + REPLACE(CONVERT(varchar(8),#Date, 1),'/','');
You can simplify the whole process, not just the year portion. Using FORMAT you can accomplish this easily.
DECLARE #TestVariable AS VARCHAR(100) = '1234'
, #Date as datetime = GetDate()
Select #TestVariable + FORMAT(#Date, 'MMddyy')
select replace(convert(varchar(20),#date,1)'/','') --or any other you need
See the docs
I'll echo others' sentiment of "do you really have to use a two-digit year"? But if you have to, I like this sort of thing
set #TestVariable = '1234'
+ right('0' + cast(month(#date) as varchar(2)), 2)
+ right('0' + cast(day(#date) as varchar(2)), 2)
+ right('0' + cast(year(#date) % 100 as varchar(2)), 2);
To talk through the general approach, I'm using right('0', «something», 2) as a means to zero pad to two places, using cast(«something» as varchar(2)) to get a string instead of a number (so implicit conversion doesn't just add zero and the relevant datepart), and finally year(#date) % 100 to get the last two digits of the date.
I have a table with columns Hour and Minute, both containing an integer. (There are other columns as well). Now, I want to create a view from this table and I need to combine these two columns' data into one column with a ':' symbol. For example, if a record has 8 for Hour, 10 for Minute, the combined column should contain 08:10. One digit numbers need to be followed by a leading 0, which initially does not exist in Hour and Minute columns.
I was successfully able to convert the integer to varchar and concatenate the numbers with ':' with the following SQL command
/* Combined Column name "Time" */
SELECT
Cast([Hour] as varchar) + ':' + Cast([Minute] as varchar) As Time
FROM Table1
but I am not sure how I can add leading 0 to this only if the number is one digit. Can someone please help me with this? Thank you.
One Other Approach :
SELECT
(CASE WHEN LEN(Cast([Hour] as varchar))=1 THEN '0'+Cast([Hour] as varchar) ELSE Cast([Hour] as varchar) END) + ':' +
(CASE WHEN LEN(Cast([Minute] as varchar))=1 THEN '0'+Cast([Minute] as varchar) ELSE Cast([Minute] as varchar) END) As Time
FROM Table1
Hope its helps you ! :)
Use timefromparts() (SQL Server 2012+) to create a proper time value:
select timefromparts(hour, minute, 0, 0, 0)
You can then format this as a string, if that is what you really want to do:
select convert(varchar(5), timefromparts(hour, minute, 0, 0, 0))
You can create scalar function to pad characters:
CREATE FUNCTION dbo.PadNumbersOnLeft (#NumberInput INT, #NoOfCharsToPad tinyint)
RETURNS VARCHAR(250)
AS BEGIN
DECLARE #ResultString VARCHAR(250)
SET #ResultString = LTRIM(#NumberInput)
IF(#NoOfCharsToPad > LEN(#ResultString))
SET #ResultString = REPLICATE('0', #NoOfCharsToPad - LEN(#ResultString)) + #ResultString;
RETURN #ResultString;
END;
And here is the example how to use this:
declare #hour int = 8
declare #minute int = 35
select
[dbo].[PadNumbersOnLeft] (#hour, 2) + ':' + [dbo].[PadNumbersOnLeft] (#minute, 2)
You can replace your columns names with #hour and #minute variables.
My function below is working for some dates but not others some, its printing minus years for some reason ie., 365 days etc.
ALTER FUNCTION [dbo].[hmsGetLosText](#FromDt as datetime) returns varchar(255)
as
BEGIN
DECLARE #YRS AS SMALLINT, #MNT AS SMALLINT, #DY AS SMALLINT, #Fvalue varchar(255)
SET #YRS = DATEDIFF(YY, #FromDt,GETDATE())
SET #MNT = DATEDIFF(MM, #FromDt,GETDATE()) % 12
SET #DY = (DATEDIFF(DD,GETDATE(), DATEADD(MM, (#YRS * 12) + #MNT,#FromDt) )*-1)
SET #Fvalue = CAST(#YRS AS VARCHAR) + ' y ' + CAST(#MNT AS VARCHAR) + ' m ' + CAST(#DY AS VARCHAR) + ' d '
RETURN #Fvalue
I would use:
set #YRS = DATEDIFF(year,#FromDt,GETDATE()) +
CASE WHEN DATEADD(year,DATEDIFF(year,#FromDt,GETDATE()),#FromDt) > GETDATE()
THEN -1 ELSE 0 END
set #FromDt = DATEADD(year,#YRS,#FromDt)
set #MNT = DATEDIFF(month,#FromDt,GETDATE()) +
CASE WHEN DATEADD(month,DATEDIFF(month,#FromDt,GETDATE()),#FromDt) > GETDATE()
THEN -1 ELSE 0 END
set #FromDt = DATEADD(month,#MNT,#FromDt)
set #DY = DATEDIFF(day,#FromDt,GETDATE())
For me, these are far more readily understood - we first get a years value that we're happy with, then add that onto #FromDt. Then we can do a direct DATEDIFF for months without much fussing around with modulo arithmetic. Similarly, once we're happy with a months value, we adjust #FromDt again so that a simple DATEDIFF gives us the correct number of days.
(You can eliminate some further calculation by first setting #YRS and then working out whether to adjust it, but not sure if that's needed here)
The reason we have to do the slight fiddle around to get the correct #YRS and #MNT values is that DATEDIFF:
Returns the count (signed integer) of the specified datepart boundaries crossed between the specified startdate and enddate.
Which is to say, that DATEDIFF(year,'20121231','20130101') returns 1 (as does DATEDIFF(year,'20120101','20131231')). Which is correct per its own definition. But we want a value that never overshoots if we add that value back onto the earlier of the two dates - so we have to compensate by sometimes subtracting 1.
Sorry to be a bother guys. I have been tasked with some code review at a client location and the laptop issued to me does not have SQL installed. While I am waiting for the installation to happen, wanted to get busy looking at the code and came across this gem
CREATE FUNCTION [dbo].[Uf_GetTotalDaysInMonth]
(
-- Add the parameters for the function here
#anydateofMonth datetime
)
RETURNS int
AS
BEGIN
-- Declare the return variable here
DECLARE #totalDaysInMonth int
-- Add the T-SQL statements to compute the return value here
DECLARE #givendate datetime
SET #givendate = STR(Year(#givendate)) + '-' + STR(Month(#givendate) + 1) + '-01'
select #totalDaysInMonth = datepart(dd, dateadd(day, -1, #givendate))
-- Return the result of the function
RETURN #totalDaysInMonth
END
Ignoring the use of needless extra variable, I believe that this function will crash in December
STR(Month(#givendate) + 1)
will evaluate to 13 and will give an out of scope date error. Could someone please validate this for me?
You vill get error in your function when pass #anydateofMonth December date.
You can use this:
CREATE FUNCTION [dbo].[Uf_GetTotalDaysInMonth]
(
-- Add the parameters for the function here
#anydateofMonth datetime
)
RETURNS int
AS
BEGIN
DECLARE #nextMonth datetime
SET #nextMonth = dateadd(m, 1, #anydateofMonth)
RETURN (SELECT Day(dateadd(d, -Day(#nextMonth), #nextMonth)))
END
http://sqlfiddle.com/#!6/185c9/7
no error on SQL Fiddle, just 13 as output
I am trying to convert my three parameters to a DATETIME but its not working. I get the error that the conversion failed when converting datetime from character string whenever I run this query. Perhaps I am doing in wrong in the conversion? If anyone can provide any feedback.
#month varchar,
#day varchar,
#year varchar
AS
DECLARE #date DATETIME
SET #date = Convert(DateTime, #month + '/' + #day + '/' + #year, 101)
Select *
From events
Where (EDate = #date) OR EDateEnd = #date OR #date Between EDate AND EDateEnd
Order By EDate ASC
You need to set the size of your parameters. Probably something like
#month varchar(2),
#day varchar(2),
#year varchar(4)
That should be working. Make sure you have provided valid values in you parameters.
Update
You should lose the 101 parameter for conversion. Provided that parameters are informed with valid values, this should work for both 2-digit and 4-digit years:
SET #date = Convert(DateTime, #month + '/' + #day + '/' + #year)
This is just a guess, because the conversion function shown should work with the proper parameters.
Are you passing in the year as a two-digit number? If so, try passing it as the full four digit year (which the "101" format expects) OR change it to
SET #date = Convert(DateTime, #month + '/' + #day + '/' + #year, 1)
if you're passing in a 2 digit year.
(See the difference for with century and without century here: http://msdn.microsoft.com/en-us/library/ms187928.aspx)
EDIT
I have a second guess... The error may not be on the line where you're explicitly converting the parameters into a Datetime variable. This has burned me before... The error MAY be occurring on the following line:
Where (EDate = #date) OR EDateEnd = (#date) OR #date Between EDate AND EDateEnd
if the EDate column or EDateEnd column is not necessaryly a DateTime column. It could be that THOSE contain the values that can't be converted to a DateTime. (They could be char fields, with a DateTime string stored in them, or they could be actual Date fields with null values stored in them.)
However, without more information about the actual schema of the database it's hard to tell. The best we can do is guess.