If all you are interested in comparing is the time, you can easily compare the sysjobschedules.active_start_time with sysjobhistory.run_time. They are in the same format (integer) so a simple equality comparison will tell you if the job (step 0) started in the same second it was expected to start. Divide them by 100 to truncate the seconds and compare minutes.
This doesn't filter the jobs by schedule, but you can easily see the Minutes comparison from the schedule vs last run time. (The schedule time is when the interval frequency is to start, so running every hour starting at 4am would show a schedule start time of 40000). You can extend this to get to your goal.
WITH cte
AS ( SELECT JobName = j.name ,
ScheduleName = sc.name ,
ScheduledTime = CAST(dbo.agent_datetime(19000101, sc.active_start_time) AS TIME(0)) ,
RunTime = CAST(dbo.agent_datetime(19000101, sjh.run_time) AS TIME(0)) ,
sc.active_start_time ,
sjh.run_time ,
RunSeq = ROW_NUMBER() OVER ( PARTITION BY j.job_id ORDER BY sc.active_start_date DESC, sc.active_start_time DESC )
FROM sysjobs AS j
INNER JOIN dbo.sysjobschedules AS sj
ON sj.job_id = j.job_id
INNER JOIN dbo.sysschedules AS sc
ON sc.schedule_id = sj.schedule_id
LEFT OUTER JOIN dbo.sysjobhistory AS sjh
ON sjh.job_id = j.job_id
AND sjh.step_id = 0
)
SELECT JobName ,
ScheduledTime ,
RunTime ,
ScheduleName ,
ScheduleTimeMinutes = cte.active_start_time / 100 ,
ActualStartMintes = cte.run_time / 100
FROM cte
WHERE cte.RunSeq = 1;
Wes
(A solid design is always preferable to a creative workaround)