• This is a fairly straitforward gaps and islands problem.  Here is a solution.  There may also be a solution with LAG, but I don't have access to a SQL 2012 environment right now to test it.

    I've set up your table using a TABLE VALUE CONSTRUCTOR.  You'll want to replace that with your actual table.

    WITH shift_groups AS
    (
      SELECT *,
       grp = ROW_NUMBER() OVER(PARTITION BY [name] ORDER BY dt, shift_type)
          - ROW_NUMBER() OVER(PARTITION BY [name], shift_type ORDER BY dt)
      FROM
      (
       VALUES
        ('Graham', 'Late', '22/10/2017')
       ,     ('Graham', 'Late', '29/10/2017')
       ,     ('Graham', 'Late', '05/11/2017') 
       ,     ('Graham', 'Morning', '12/11/2017')
       ,     ('Graham', 'Afternoon', '19/11/2017')
       ,     ('Graham', 'Afternoon', '26/11/2017')
       ,     ('Graham', 'Afternoon', '03/12/2017')
       ,     ('Graham', 'Late', '10/12/2017')
       ,     ('Graham', 'Late', '17/12/2017')
      ) m([name], shift_type, sunday_shift_date)
      CROSS APPLY (VALUES(CONVERT(DATE, sunday_shift_date, 103))) dt(dt)
    )
    SELECT [name], shift_type, MIN(dt), MAX(dt)
    FROM shift_groups
    GROUP BY [name], shift_type, grp
    ORDER BY [name], MIN(dt)

    Drew

    J. Drew Allen
    Business Intelligence Analyst
    Philadelphia, PA