I'm going to write a code that round a datetime value but i can't compare which ones is more efficient:
DECLARE #DateValue DATETIME = '2021-01-13 11:59:59'
---- FIRST SOLUSTION:
SELECT CAST(#DateValue AS smalldatetime) AS DateRoundS1
---- SECOND SOLUTION:
SELECT CONVERT(smalldatetime, #DateValue) AS DateRoundS2
---- THIRD SOLUTION:
SELECT DATEADD(HOUR, DATEDIFF(HOUR, 0, #DateValue), 0) AS DateRoundS3
---- FORTH SOLUTION:
DECLARE #DateValue DATETIME = '2021-01-13 11:59:59'
DECLARE #DiffMinsTime INT = DATEPART(MINUTE,#DateValue)
DECLARE #DiffSecsTime INT = DATEPART(SECOND,#DateValue)
DECLARE #DiffMSTime INT = DATEPART(MILLISECOND,#DateValue)
IF( #DiffMinsTime > 0 )
BEGIN
SELECT DATEADD(MINUTE,DATEDIFF(MINUTE,#DiffMinsTime,#DateValue),0)
END
IF(#DiffSecsTime > 0)
BEGIN
SELECT DATEADD(SECOND,DATEDIFF(SECOND,#DiffSecsTime,#DateValue),0)
END
IF(#DiffMSTime > 0)
BEGIN
SELECT DATEADD(MILLISECOND,DATEDIFF(MILLISECOND,#DiffMSTime,#DateValue),0)
END
PS: I know the last one has overflow!!
Is there any more efficient way to do that?!
With conversions and transformations it always depends on lots of factors.
Best way: Build a test rig and set aside a few minutes or better hours.
The test rig creates numbers from 0 to 9 999 999 - about 10 million rows. Kudos to Jeff Moden for the SQL spackle that creates the number list.
DROP TABLE IF EXISTS #numbers
;
DROP TABLE IF EXISTS #dates
;
CREATE TABLE
#numbers
(
number integer NOT NULL
)
;
CREATE TABLE
#dates
(
dated datetime2(7) NOT NULL
)
;
WITH
cteNum
(
smallnum
)
AS
(
SELECT Cast( 1 AS integer )
UNION ALL
SELECT Cast( 2 AS integer )
UNION ALL
SELECT Cast( 3 AS integer )
UNION ALL
SELECT Cast( 4 AS integer )
UNION ALL
SELECT Cast( 5 AS integer )
UNION ALL
SELECT Cast( 6 AS integer )
UNION ALL
SELECT Cast( 7 AS integer )
UNION ALL
SELECT Cast( 8 AS integer )
UNION ALL
SELECT Cast( 9 AS integer )
UNION ALL
SELECT Cast( 0 AS integer )
)
INSERT INTO
#numbers
(
number
)
SELECT
num1.smallnum * 1000000 + num2.smallnum * 100000 + num3.smallnum * 10000 + num4.smallnum * 1000
+ num5.smallnum * 100 + num6.smallnum * 10 + num7.smallnum
FROM
cteNum AS num1
CROSS JOIN cteNum AS num2
CROSS JOIN cteNum AS num3
CROSS JOIN cteNum AS num4
CROSS JOIN cteNum AS num5
CROSS JOIN cteNum AS num6
CROSS JOIN cteNum AS num7
;
INSERT INTO
#dates
(
dated
)
SELECT
Cast( DateAdd( ms, nums.number, dated.basedate) AS datetime2(7) ) AS dated
FROM
#numbers AS nums
CROSS JOIN
(
SELECT Cast(GetDate() AS datetime2(7) ) AS basedate
) dated
;
DROP TABLE IF EXISTS #numbers
;
This will take from a couple of seconds to a couple of minutes to create.
Using a table minimises the amount of effort to table maintenance done by the query analyzer.
The test of conversion times can then be done in a controlled environment. Tip: Using a start and end time capture eliminates the overhead for a SQL trace.
SET NOCOUNT ON
;
DECLARE
#datetimestarted datetime2(7),
#datetimeended datetime2(7),
#result varchar(200),
#crlf char(2) = char(13) + char(10)
;
SET #datetimestarted = Getdate()
;
SELECT
dated,
datedrounded = Cast( dated AS datetime2(0) )
FROM
#dates
;
SET #datetimeended = Getdate()
;
SET #result = 'Processing time = ' + Cast( Datediff( ms, #datetimestarted, #datetimeended ) / 1000 AS varchar(12) ) + ' seconds' + #crlf
+ ' > Start time: ' + Convert( varchar(20), #datetimestarted, 126 ) + #crlf
+ ' > End time: ' + Convert( varchar(20), #datetimeended, 126 ) + #crlf
;
PRINT #result
;
SET #datetimestarted = Getdate()
;
SELECT
dated,
datedrounded = Convert( datetime2(0), dated )
FROM
#dates
;
SET #datetimeended = Getdate()
;
SET #result = 'Processing time = ' + Cast( Datediff( ms, #datetimestarted, #datetimeended ) / 1000 AS varchar(12) ) + ' seconds' + #crlf
+ ' > Start time: ' + Convert( varchar(20), #datetimestarted, 126 ) + #crlf
+ ' > End time: ' + Convert( varchar(20), #datetimeended, 126 ) + #crlf
;
PRINT #result
;
Run time on my VM is about 3 minutes for each option with Cast taking a tad bit longer than Convert. Now this depends on what one wants to achieve so feel free to change the transformations as required.
And finally the clean up.
DROP TABLE IF EXISTS #dates
;
Final tip: date and datetime are kind of obsolete datetime types in SQL Server. Calculation with these is actually easier than the new datetime2 type allowing mathematical calculations.
datetime2 requires the Dateadd function use.
However datetime2 is easier to convert to current database interactions between different types of RDBMS. Also easier to work in standard ISO 8601 formats which makes transferring data between different parts of the world a whole lot easier.
Related
I am a newbie in SQL and i really need your help for my project. So, i had to create a master calendar table (which i have already created with the name "DimDate") but the problem is that i can't define right the function for the Easter Holidays in Greece.
I'm trying to create a function which will return the Easter Holidays (e.g Easter Sunday, Easter Monday, Good Friday) using the Meeus's Julian algorithm and not the Gregorian.
The function i have already tried, concerns the Gregorian calendar and as a result i get wrong dates for most of Easter Sundays. For example, for the year 2015, i see from the result of my query that the Easter Sunday was on 05/04/2015 (dd/MM/yyy) BUT the truth is that on 2015 the real date of Easter Sunday in Greece was 12/04/2015. And this is because i used the Gregorian algorithm as you can see below in the code i used.
CREATE FUNCTION dbo.GetEasterHolidays(#year INT)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
WITH x AS
(
SELECT [Date] = CONVERT(DATE, RTRIM(#year) + '0' + RTRIM([Month])
+ RIGHT('0' + RTRIM([Day]),2))
FROM (SELECT [Month], [Day] = DaysToSunday + 28 - (31 * ([Month] / 4))
FROM (SELECT [Month] = 3 + (DaysToSunday + 40) / 44, DaysToSunday
FROM (SELECT DaysToSunday = paschal - ((#year + #year / 4 + paschal - 13) % 7)
FROM (SELECT paschal = epact - (epact / 28)
FROM (SELECT epact = (24 + 19 * (#year % 19)) % 30)
AS epact) AS paschal) AS dts) AS m) AS d
)
SELECT [Date], HolidayName = 'Easter Sunday' FROM x
UNION ALL SELECT DATEADD(DAY,-2,[Date]), 'Good Friday' FROM x
UNION ALL SELECT DATEADD(DAY, 1,[Date]), 'Easter Monday' FROM x
);
--- Now 'updating' my "DimDate" calendar table---
;WITH x AS
(
SELECT d.[Date], d.IsHolidayEU, d.HolidayEU, h.HolidayName
FROM dbo.DimDate AS d
CROSS APPLY dbo.GetEasterHolidays(d.[Year]) AS h
WHERE d.[Date] = h.[Date]
)
UPDATE x SET IsHolidayEU = 1, HolidayEU = HolidayName;
I have searched the internet extensively and i found what i wanted but in HANA, not sql. I am confused since i tried to convert the HANA Code i found into sql but didn't manage it.
Also, here is the link from the HANA code i found, it contains 2 pictures.
I think i need to convert the second (image) code into sql server statements.
https://blogs.sap.com/2015/04/08/happy-easter-folks-easter-date-calculation/
Please help me if you can...and thank you in advance.
*Sorry for the looks of the code, i am new here, i couldn't find the way to make it better in order to be whole inside the "grey" area
It is a great function that works great at least until 2100.
In order to not have performance issues create a temp table with the given dates like this:
WITH estdates as
(SELECT c.fd EasterSunday
, c.[Year]
, DATEADD(dd,-2,c.fd) EasterFriday
, DATEADD(dd,1,c.fd) EasterMonday
FROM
(
SELECT dbo.UDF_GetEaster_Orthodox( ur.YR) fd,ur.YR [Year]
FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY N1.N) +1999 AS YR
FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1)) AS N1(N)
CROSS JOIN (VALUES(1),(1),(1),(1),(1),(1),(1),(1)) AS N2(N)
) AS ur
) c
)
select *
into #EasterHolidays
from
(SELECT EasterFriday EasterHolidays FROM estdates d
UNION ALL
SELECT EasterMonday FROM estdates d ) a
I finally managed to get the right results with the following code.
The first function gives the Easter Sunday:
CREATE FUNCTION dbo.Easter_Orthodox22(#YEAR INT)
RETURNS DATE
AS
BEGIN
DECLARE #EasterMonth INT,
#EasterDay INT,
#Easter NVARCHAR(10),
#EYear VARCHAR(4),
#EMonth VARCHAR(2),
#EDay VARCHAR(2),
#EasterDate DATE,
#a INT,
#b INT,
#c INT,
#d INT,
#e INT;
SET #a = #YEAR%4;
SET #b = #YEAR%7;
SET #c = #YEAR%19;
SET #d = (19 * #c + 15)%30;
SET #e = (2 * #a + 4 * #b - #d +34)%7;
SET #EasterDay = (((#d + #e + 114)%31)+1);
SET #EasterMonth = CAST(((#d + #e + 114)/31) AS INT);
SET #EYear = CAST( #YEAR AS VARCHAR(4));
SET #EMonth = CAST( #EasterMonth AS VARCHAR(2));
SET #EDay = CAST( #EasterDay AS VARCHAR(2));
SET #Easter = CONCAT( CONCAT( #EYear, RIGHT( CONCAT('0', #EMonth),2)), RIGHT ( CONCAT('0', #EDay),2));
SET #EasterDate = CAST( #Easter AS DATE);
SET #EasterDate = DATEADD( day, 13, #EasterDate);
RETURN #EasterDate;
END
GO
Then, i created two more functions in order to find the Easter Monday and Great Friday:
CREATE FUNCTION dbo.GetEasterMonday2 (#YEAR INT)
RETURNS DATE
AS
BEGIN
RETURN (SELECT convert(date,convert(datetime,dbo.Easter_Orthodox2(#YEAR)) + 1))
END
GO
CREATE FUNCTION dbo.GetGoodFriday2 (#YEAR INT)
RETURNS DATE
AS
BEGIN
RETURN (SELECT convert(date,convert(datetime,dbo.Easter_Orthodox2(#YEAR)) - 2))
END
GO
But, now i am facing a different problem! A performance one, when i try to update my master calendar. I do the following in order to update the calendar:
UPDATE [dbo].[DimDate]
SET IsHolidayEU = 1,
HolidayEU = 'Easter Sunday'
WHERE [DATE] = dbo.Easter_Orthodox22(#CurrentYear)
UPDATE [dbo].[DimDate]
SET IsHolidayEU = 1,
HolidayEU = 'Good Friday'
WHERE [DATE] = dbo.GetGoodFriday2(#CurrentYear)
UPDATE [dbo].[DimDate]
SET IsHolidayEU = 1,
HolidayEU = 'Easter Monday'
WHERE [DATE] = dbo.GetEasterMonday2(#CurrentYear)
These Update expression are written inside a while loop inside my calendar code..I think that i should have used the "SCHEMABINDING" and/or "CROSS APPLY" with "with-query" that is exhibited in the primary code but don't know how to change my code into that in order to improve the performance..Any help appreciated guys!
So I have this table that has date columns in int type.
last_run_date | last_run_time
20171116 | 100234
Im trying to convert this two values into a datetime to be used in datediff statement.
this is my statement
SELECT 1
FROM V_Jobs_All_Servers vjas
WHERE JobName='DailyReports_xxxx' and Step_Name='xxxx'
and DATEDIFF(hour, Convert(varchar,STUFF(STUFF(STUFF(STUFF(STUFF(cast(
Convert(varchar(100),vjas.last_run_date) + Convert(varchar(100),vjas.last_run_time) as varchar)
,5,0,'-'),8,0,'-'),11,0,' '),14,0,':'),17,0,':')), Getdate()) <3
This works but only when the last_run_time value is in two digits hour format
101216, but whenever its one digit hour 91316 it fails with the following error,
The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value.
I am on SQL Server 2005
If you're getting this value from msdb.dbo.sysjobsteps, there's a built-in function, msdb.dbo.agent_datetime(), to convert last_run_date and last_run_time to a datetime already:
select job_id,
step_id,
step_name,
msdb.dbo.agent_datetime(nullif(last_run_date,0),nullif(last_run_time,0)) as last_run_datetime
from msdb.dbo.sysjobsteps
It is an undocumented function. However, at least in my version of SQL Server (2012), that function has this definition:
CREATE FUNCTION agent_datetime(#date int, #time int)
RETURNS DATETIME
AS
BEGIN
RETURN
(
CONVERT(DATETIME,
CONVERT(NVARCHAR(4),#date / 10000) + N'-' +
CONVERT(NVARCHAR(2),(#date % 10000)/100) + N'-' +
CONVERT(NVARCHAR(2),#date % 100) + N' ' +
CONVERT(NVARCHAR(2),#time / 10000) + N':' +
CONVERT(NVARCHAR(2),(#time % 10000)/100) + N':' +
CONVERT(NVARCHAR(2),#time % 100),
120)
)
END
You are massively over complicating this, just pad your time value with a leading 0 and convert from there:
declare #t table(last_run_date int, last_run_time int);
insert into #t values(20171116,90234),(20171116,100234);
select last_run_date
,last_run_time
,convert(datetime,cast(last_run_date as nvarchar(8))
+ ' '
+ stuff(stuff(right('0' + cast(last_run_time as nvarchar(6))
,6)
,5,0,':')
,3,0,':')
,112) as DateTimeData
from #t
Output:
+---------------+---------------+-------------------------+
| last_run_date | last_run_time | DateTimeData |
+---------------+---------------+-------------------------+
| 20171116 | 100234 | 2017-11-16 09:02:34.000 |
| 20171116 | 100234 | 2017-11-16 10:02:34.000 |
+---------------+---------------+-------------------------+
Here's an ugly way...
declare #table table (last_run_date int, last_run_time int)
insert into #table
values
(20171116,100234),
(20171116,91316)
select
cast(cast(cast(last_run_date as varchar) as datetime) + ' ' + stuff(stuff(last_run_time,len(last_run_time) - 1,0,':'),len(stuff(last_run_time,len(last_run_time) - 1,0,':')) - 4,0,':') as datetime)
from #table
DECLARE #temp TABLE (last_run_date int, last_run_time int)
INSERT INTO #temp VALUES (20171116, 100234)
SELECT convert(datetime,CAST(last_run_date as varchar))
+ Convert(time, Dateadd(SECOND, Right(last_run_time,2)/1
,Dateadd(MINUTE, Right(last_run_time,4)/100
,Dateadd(hour, Right(last_run_time,6)/10000
,'1900-01-01'
)
)
)
) [DateConverted]
FROM #temp
Produces Output:
DateConverted
2017-11-16 10:02:34.000
You can see how this works by doing each part individually.
SELECT Dateadd(hour, Right(last_run_time,6)/10000
,'1900-01-01')
FROM #temp
Gives the hours position.
SELECT Dateadd(MINUTE, Right(last_run_time,4)/100
,Dateadd(hour, Right(last_run_time,6)/10000
,'1900-01-01'))
FROM #temp
Gives the hours plus minutes position.
Etc.
I'm trying to port some T-SQL to Hive SQL and am running into trouble with the following statement:
create table param as
select convert( int, CONVERT( char(8), convert( date, begin_date ), 112 ) ) as begin_dtkey
, convert( int, CONVERT( char(8), convert( date, end_date ), 112 ) ) as end_dtkey
, convert( int, CONVERT( char(8), convert( date, cutoff_date ), 112 ) ) as cutoff_dtkey
, *
from tmp_param;
The idea is to convert dates to their integer formats. Is there a way to do this in Hive (v0.13)?
In the case of T-SQL this was a select...into statement, but I went ahead and made it create table...as select for Hive.
Probably the easiest way -- and one that should work in both databases -- is to use the date part extraction functions:
select (year(begin_date) * 10000 + month(begin_date) * 100 + day(begin_date)) as begin_dtkey,
(year(end_date) * 10000 + month(end_date) * 100 + day(end_date)) as end_dtkey,
(year(cutoff_date) * 10000 + month(cutoff_date) * 100 + day(cutoff_date)) as cutoff_dtkey,
p.*
from tmp_param p;
I have written a pivot query in sql server 2012. It works fine and it shows the result of usernames under Rows and sum of production hours in seconds under columns. But I need the seconds to be splitted into hours:minutes format. Please help me on query.
declare #empid nvarchar(20), #fromdate date, #todate date, #cols nvarchar(max), #query AS VARCHAR(MAX), #dt varchar(20), #dt1 varchar(20)
set #empid = 'EC0100'
set #fromdate = '10/01/13'
set #todate = '10/31/13'
set #dt='Exceptions'
set #dt1='Tech Issues'
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(convert(nvarchar(20),c._Date, 101))
FROM MIS_BM_Calendar c
where c._Date between #fromdate and #todate and _Day not in
('Sunday')
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query= 'select UserName, '+#cols+' from
(select e.UserName, c._Date , (SUM(DATEDIFF(SS,0,c.TimeTaken))) As TimeTaken
from MIS_BM_Users e
inner join MIS_Opus c
on e.EmpId=c.EmpId
where (e.AccountManagerID='''+#empid+''') and c.Category not in ('''+#dt+''','''+#dt1+''')
group by c._Date, e.UserName
) As SourceTable
Pivot
(
SUM(TimeTaken) for _Date in ('+#cols+')
) As Pvt'
execute(#query)
The amount of seconds in a minute and in an hour is constant. 60 seconds in a minute, 3600 seconds in an hour. Pivot query has no impact on this.
Thus, your question becomes how can I convert seconds into hours, minutes and seconds. Since you're on 2012, you have the handy dandy TimeFromParts function and so you can see you need to feed it hours, minutes and seconds
WITH SRC (TimeTaken) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM sys.all_columns AS AC
)
, Proof AS
(
-- this logic is valid as long as TimeTaken is less than 24 hours
-- or 86400 (24 * 60 * 60) seconds
SELECT
SRC.TimeTaken
-- integer division drops remainder
, SRC.TimeTaken / 3600 AS Hours
-- integer division and modulo operator to keep legit values
, (SRC.TimeTaken / 60) % 60 AS Minutes
-- modulo to have values 0 - 59
, SRC.TimeTaken % 60 AS Seconds
FROM
SRC
)
SELECT
P.TimeTaken
, P.Hours
, P.Minutes
, P.Seconds
, TIMEFROMPARTS(P.Hours, P.Minutes, P.Seconds, 0, 0) AS TimeTakenTimeType
FROM
Proof AS P;
SQLFiddle
I have created a scalar function and converted the seconds to HHMMSS. Then include the function in the main query.
ALTER function [dbo].[ConvertSecondsToHHMMSS]
(
#TotalSeconds int
)
Returns nvarchar(20)
As
Begin
declare #hours int, #minutes int, #seconds int, #result nvarchar(20)
set #hours = #TotalSeconds / 3600
set #minutes = (#TotalSeconds % 3600) / 60
set #seconds = #TotalSeconds % 60
set #result = CONVERT(nvarchar(20),#hours) + ':' + CONVERT(nvarchar(20),#minutes) + ':' +CONVERT(nvarchar(20),#seconds)
return #result
end
Main Query:
set #query= 'select UserName, '+#cols+' from
(
select e.UserName, c._Date, dbo.ConvertSecondsToHHMMSS(SUM(DATEDIFF(SS,0,c.TimeTaken))) As TimeTaken from MIS_BM_Users e
inner join MIS_Opus c on e.EmpId=c.EmpId
where (e.AccountManagerID='''+#AccountManagerId+''')
and c.Category not in ('''+#Condition1+''', '''+#condition2+''')
group by c._Date, e.UserName
) As SourceTable
Pivot
(
MIN(TimeTaken) for _Date in ('+#cols+')
) As Pvt'
execute(#query)
I want to use a date-time picker to select a date as well as the time component. The calender allows me to pick a date but there's no possibility to choose the a specific time.
I want to choose a start and end time, to select a subset out of lot of a data.
I had a similar issue in my current project. My solution is to add a field for the date (type of date/time) and a field for the time. The time field will show a drop down list containing the 24 hours text for users to select (refer to attach screenshot below).
The steps to create the dropdown list is simple:
Open the propery of the time parameter of the report
Select Available Values (refer to attached screenshot below)
Select Specify values and add values to represent the 24 hours.
Please note, you can also set the available values from a query.
In addition, the stored procedure where the report data are retrieved should convert the date and time passed from the report to datetime type to get it work. Below shows a sample:
#StartDateTime = CONVERT(datetime, convert(nvarchar, #StartDate) +
' ' + CONVERT(nvarchar(12), #starttime))
Hope it helps.
I'm sure we have all found a way around this by now, however here is my solution.
CREATE PROCEDURE [ssrs].[Params_GetTimeTable]
(
#hr_from int = 0,
#hr_to int = 24,
#min_interval int = 15
)
AS
BEGIN
-- Internal Variables
declare #hr int = #hr_from
declare #min int = 0
declare #timetable table
(
hhmm varchar(5)
)
-- Populate the #timetable
while #hr < #hr_to
begin
while #min < 60
begin
insert into #timetable(hhmm)
select
case
when #hr < 10 then '0' + cast(#hr as varchar(2)) + ':' + case when #min < 10 then '0' + cast(#min as varchar(2)) else cast(#min as varchar(2)) end
else cast(#hr as varchar(2)) + ':' + case when #min < 10 then '0' + cast(#min as varchar(2)) else cast(#min as varchar(2)) end
end
set #min = #min + #min_interval
end
set #hr = #hr + 1
set #min = 0
end
-- Add a finishing time to the output table
insert into #timetable(hhmm)
select
case
when #hr < 10 then '0' + cast(#hr as varchar(2)) + ':00'
else cast(#hr as varchar(2)) + ':00'
end
-- Return the output
select hhmm from #timetable
END
Test the result by:
EXEC [ssrs].[Params_GetTimeTable] 0, 24, 15
Output :
hhmm
00:00
00:15
00:30
00:45
01:00
01:15
...
23:00
23:15
23:30
23:45
24:00
With the standard SSRS calendar picker, after you have selected a date, you can click in the textbox and manually enter the time value next to the selected date. I know this is not very user intuitive, but it does work.
I have the same problem, and am looking for a more user friendly solution, but this is all I can come with so far.
I use this SQL which generates times every 15mins between 9:00 and 21:00, people is just any table with at least enough rows i.e. 12 or 24.
select time1
from
(
select hr || ':' || mm time1
from
(
select '09' hr
from dual
union
select cast(rownum + 9 as varchar(2)) hr
from people
where rownum < 12
order by hr
)hr,
(
select '00' mm
from dual
union
select '15' mm
from dual
union
select '30' mm
from dual
union
select '45' mm
from dual
)mm
union
(
select '21:00' time1
from dual
)
)T1
order by time1
I use this as an integer parameter then you can add the number of minutes to whatever date is selected
DECLARE #interval INT = 15
;WITH cteM AS (
SELECT 0 M UNION ALL
SELECT M+#interval FROM cteM
WHERE M+#interval <= 59
),
cteH AS (
SELECT 0 H UNION ALL
SELECT H+1 FROM cteH
WHERE H+1 < 24
)
SELECT
RIGHT('0' + CAST(cteH.H AS varchar(2)), 2) + ':' + RIGHT('0' + CAST(cteM.M AS varchar(2)), 2) Label,
cteH.H*60 + cteM.M Value
FROM cteM CROSS JOIN cteH