Join Comma Separated Same Value create table dbo.CourseMaster
(
  CourseId char(2),
  CourseName char(3)
);

create table dbo.StudentMaster
(
  ROLLNO char(5),
  NAME varchar(10),
  ADDRESS varchar(20),
  Course varchar(100)
);

insert into dbo.CourseMaster values
('01', 'ABC'),
('02', 'DEF'),
('03', 'GHI'),
('04', 'JKL'),
('05', 'MNO'),
('06', 'PQR'),
('07', 'STU');

insert into dbo.StudentMaster values
('12345', 'RAM',   'RAM ADDRESS',   '01,02,02'),                      
('25695', 'HARI',  'HARI ADDRESS',  '02,06'),                         
('89685', 'JEFF',  'JEFF ADDRESS',  '03,05,06,07'),                   
('47896', 'DAISY', 'DAISY ADDRESS', '03');


Query 1:

select SM.ROLLNO,
       SM.NAME, 
       SM.ADDRESS,
       (
       select ','+CM.CourseName
       from dbo.CourseMaster as CM
       where ','+SM.Course+',' like '%,'+CM.CourseId+',%'
       for xml path(''), type
       ).value('substring(text()[1], 2)', 'varchar(max)') as Course
from dbo.StudentMaster as SM;


Actual Ouput:

| ROLLNO |  NAME |       ADDRESS |          Course |
|--------|-------|---------------|-----------------|
|  12345 |   RAM |   RAM ADDRESS |         ABC,DEF |
|  25695 |  HARI |  HARI ADDRESS |         DEF,PQR |
|  89685 |  JEFF |  JEFF ADDRESS | GHI,MNO,PQR,STU |
|  47896 | DAISY | DAISY ADDRESS |             GHI |


When I add course like 01,02,02 in student master it give below output:
ABC,DEF and it should give: ABC,DEF,DEF
Normalising StudentMaster.Course will help preserve duplicates. Since you've tagged sql-server-2012 sadly string_split() is unavailable. Happily, the internet is rife with pre-2016 workarounds. I'll choose this one arbitrarily since it was the top google hit for me. 

Given creation of dbo.fn_split_string_to_column() from the linked SO post, the following should get you what you seek.

with normal_course as (
    select SM.ROLLNO,
           ss.column_id,
           ss.value as course_id
    from dbo.StudentMaster as SM
    cross apply dbo.fn_split_string_to_column(SM.Course,',') as ss
)
select SM.ROLLNO,
       SM.NAME, 
       SM.ADDRESS,
       (
       select ','+CM.CourseName
       from normal_course as nc 
       join dbo.CourseMaster as CM on CM.CourseId = nc.course_id
       where nc.ROLLNO = SM.ROLLNO
       for xml path(''), type
       ).value('substring(text()[1], 2)', 'varchar(max)') as Course
from dbo.StudentMaster as SM;


Try it on dbfiddle

Of course, my preference would also be to move the subselect down to a dedicated apply, but that's not strictly required.

Explanation

In your original query, the WHERE clause in your sub-select is fuzzy-matching the CourseId to the comma-aggregated string Course. This "mostly works" as you can see; but one of the (many) downsides of this approach is what you have seen - that each CourseId matches only once and in-line "duplicates" will not be aggregated multiple times. 

Splitting out StudentMaster.Course into normalised values occurs in the CTE (with block) at the top of the query. This preserves the duplicates.

    select SM.ROLLNO,
           ss.column_id,
           ss.value as course_id
    from dbo.StudentMaster as SM
    cross apply dbo.fn_split_string_to_column(SM.Course,',') as ss


For the example duplicate row, this shows us...

+--------+-----------+-----------+
| ROLLNO | column_id | course_id |
+--------+-----------+-----------+
| 12345  | 1         | 01        |
| 12345  | 2         | 02        |
| 12345  | 3         | 02        |
+--------+-----------+-----------+


Now that the duplicate course_id is exposed as a separate data record, when you re-aggregate the corresponding CourseNames, the duplicates will be preserved unless you take steps to explicitly remove them.