In SQL Server 2005 and up, you can use recursive CTEs (example based on this article):
DECLARE @t AS TABLE (domainid INT NOT NULL, domainname VARCHAR(25) NOT NULL, parentdomainid INT NULL);
INSERT INTO @t VALUES (1, 'Law', NULL);
INSERT INTO @t VALUES (3, 'Engineering', NULL);
INSERT INTO @t VALUES (4, 'Medical', NULL);
INSERT INTO @t VALUES (6, 'Civil', 3);
INSERT INTO @t VALUES (7, 'Mechanical', 3);
INSERT INTO @t VALUES (8, 'Dental', 4);
INSERT INTO @t VALUES (9, 'MBBS', 4);
INSERT INTO @t VALUES (12, 'Cavity', 8);
-- SELECT * FROM @t;
WITH CTE(domainid, parentdomainid, domainname, Depth, SortCol)
AS
(
SELECT domainid, parentdomainid, domainname, 0, CAST(domainid AS varbinary(max))
FROM @t
WHERE parentdomainid IS NULL
UNION ALL
SELECT d.domainid, d.parentdomainid, d.domainname, p.Depth + 1,
CAST(SortCol + CAST(d.domainid AS binary(4)) AS varbinary(max))
FROM @t AS d
JOIN CTE AS p
ON d.parentdomainid = p.domainid
)
SELECT domainid, parentdomainid, domainname, Depth, REPLICATE('--', Depth) + domainname as displayname
FROM CTE
ORDER BY SortCol;