SQL, Concatenate a character and leading 0 depending on the value - sql

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.

Related

Is there a simpler method for getting the two digit year?

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.

How to set month and day from one table to new stored procedure

declare
#pm_WeekEndDate DATETIME,
#lp_Day VARCHAR(10),
#intDate DATETIME
set #pm_WeekEndDate = MONTH(#pm_WeekEndDate)
set #lp_Day = day(#pm_WeekEndDate)
set #intDate = (#pm_WeekEndDate & #lp_Day)
This code should take month january then = 1 because other table has all in numbers like month 1 to 12 and day 1 to 7.
But I am getting this error:
Msg 402, Level 16, State 1, Procedure PRO, Line60
The data types datetime and varchar are incompatible in the '&' operator.
This is purely a guess by on extremely vague details and having this kind of poor table design in the past. Is something like this what you are looking for?
declare #pm_WeekEndDate DATETIME = getdate()
select #pm_WeekEndDate
declare #DateVal char(4)
select #DateVal = right('00' + convert(varchar(2), MONTH(#pm_WeekEndDate)), 2) + right('00' + convert(varchar(2), DAY(#pm_WeekEndDate)), 2)
select #DateVal
Please notice that you can't have the result be a date because it doesn't make sense. I am guessing that your table has dates stored as either strings or ints??

Select length as minute:seconds format

Trying to convert seconds to a minute:seconds format.
e.g. 207 seconds would be 3:27
I have a table with column length that has the length of songs stored in seconds.
Using this query almost works, however, when a song should be 3:03 it will instead show 3:3
select concat(Length/60, ':', Length%60) as Length from songs
SELECT Convert(nvarchar, (Length/60)) + ':' + RIGHT('0' + Convert(nvarchar, Length%60), 2) as Length from songs
I build this using a varaible since I didn't have your table, but try this:
declare #length int = 207
select concat(#Length/60, ':', case len(#Length%60) when 1 then '0' else '' end, #Length%60) as [leng]
You can use dateadd to do that:
select convert(varchar, dateadd(second, 187, 0), 108)
This returns "00:03:07" so you can cut away hours if you don't need them.

returning weird dates function to calculate length of serice

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.

Put condition on select command : charindex - SQL

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