Try this:
DECLARE @tbl TABLE (ID INT, [SUB.] NVARCHAR(30), GRADE NVARCHAR(5))
INSERT INTO @tbl (ID, [SUB.], GRADE)
VALUES(1, 'MATHS', 'D')
INSERT INTO @tbl (ID, [SUB.], GRADE)
VALUES(1, 'ENGLISH', 'B-')
INSERT INTO @tbl (ID, [SUB.], GRADE)
VALUES(1, 'SCIENCE', 'A')
INSERT INTO @tbl (ID, [SUB.], GRADE)
VALUES(2, 'MATHS', 'A')
INSERT INTO @tbl (ID, [SUB.], GRADE)
VALUES(2, 'ENGLISH', 'B')
INSERT INTO @tbl (ID, [SUB.], GRADE)
VALUES(2, 'SCIENCE', 'B-')
INSERT INTO @tbl (ID, [SUB.], GRADE)
VALUES(3, 'MATHS', 'B+')
INSERT INTO @tbl (ID, [SUB.], GRADE)
VALUES(3, 'ENGLISH', 'A')
INSERT INTO @tbl (ID, [SUB.], GRADE)
VALUES(3, 'SCIENCE', 'A')
SELECT t1.ID, MATHS, ENGLISH, SCIENCE
FROM (
SELECT ID, GRADE AS 'MATHS'
FROM @tbl
WHERE [SUB.] = 'MATHS'
) AS t1 INNER JOIN (
SELECT ID, GRADE AS 'ENGLISH'
FROM @tbl
WHERE [SUB.] = 'ENGLISH'
) AS t2 ON t1.ID = t2.ID INNER JOIN (
SELECT ID, GRADE AS 'SCIENCE'
FROM @tbl
WHERE [SUB.] = 'SCIENCE'
) AS t3 ON t2.ID = t3.ID
Result:
1 D B- A
2 A B B-
3 B+ A A
Read about
JOIN's[
^]
To beeter understan, see this:
Visual Representation of SQL Joins[
^]
[EDIT #1]
Ok, if you want to fetch data in dynamic way, we need to do some trick. See example:
IF (OBJECT_ID('#tbl') IS NOT NULL) DROP TABLE #tbl
CREATE TABLE #tbl (ID INT, [SUB.] NVARCHAR(30), GRADE NVARCHAR(5))
INSERT INTO #tbl (ID, [SUB.], GRADE)
VALUES(1, 'MATHS', 'D')
INSERT INTO #tbl (ID, [SUB.], GRADE)
VALUES(1, 'ENGLISH', 'B-')
INSERT INTO #tbl (ID, [SUB.], GRADE)
VALUES(1, 'SCIENCE', 'A')
INSERT INTO #tbl (ID, [SUB.], GRADE)
VALUES(2, 'MATHS', 'A')
INSERT INTO #tbl (ID, [SUB.], GRADE)
VALUES(2, 'ENGLISH', 'B')
INSERT INTO #tbl (ID, [SUB.], GRADE)
VALUES(2, 'SCIENCE', 'B-')
INSERT INTO #tbl (ID, [SUB.], GRADE)
VALUES(3, 'MATHS', 'B+')
INSERT INTO #tbl (ID, [SUB.], GRADE)
VALUES(3, 'ENGLISH', 'A')
INSERT INTO #tbl (ID, [SUB.], GRADE)
VALUES(3, 'SCIENCE', 'A')
IF (OBJECT_ID('#Grades') IS NOT NULL) DROP TABLE #Grades
CREATE TABLE #Grades (IDG INT IDENTITY(1,1), GRADE NVARCHAR(5))
INSERT INTO #Grades (GRADE)
SELECT DISTINCT GRADE
FROM #tbl
DECLARE @cols NVARCHAR(200)
SET @cols = STUFF((SELECT DISTINCT '],[' + [SUB.]
FROM #tbl
ORDER BY '],[' + [SUB.]
FOR XML PATH('')),1,2,'') + ']'
DECLARE @dt NVARCHAR(2000)
SET @dt = 'SELECT t1.ID, t1.[SUB.], t2.IDG ' +
'FROM #tbl AS t1 INNER JOIN #Grades AS t2 ON t1.GRADE = t2.GRADE'
DECLARE @pt NVARCHAR(MAX)
SET @pt = 'SELECT ID, ' + @cols + ' ' +
'FROM (' + @dt + ') AS DT ' +
'PIVOT(MAX(IDG) FOR [SUB.] IN(' + @cols + ')) AS PT '
EXEC(@pt)
DROP TABLE #Grades
DROP TABLE #tbl
Result:
ID ENGLISH MATHS SCIENCE
1 3 5 1
2 2 1 3
3 1 4 1
Change the code to your needs ;)
[EDIT]