1) Я переписал ваш SQL как:
WITH trash_list AS (
SELECT cm.id,
cm.datetime,
cm.subject,
cm.createdby,
cm.toreceipientid,
cm.senderstatus AS Status
FROM COMPOSEMAIL cm
WHERE cm.createdBy = @p
AND cm.enderStatus IN(7, 8)
UNION
SELECT cm.id,
cm.datetime,
cm.subject,
cm.createdby,
cm.toreceipientid,
cm.receiverstatus AS Status
FROM COMPOSEMAIL cm
WHERE cm.toreceipientid = @p1
AND cm.receiverstatus IN (7, 8))
SELECT t.id,
t.datetime,
t.subject,
t.createdby,
t.toreceipientid,
t.status
FROM (SELECT tl.id,
tl.datetime,
tl.subject,
tl.createdby,
tl.toreceipientid,
tl.status,
ROW_NUMBER() OVER(ORDER BY '+ @p_SortExpression +') AS Indexing
FROM trash_list tl
GROUP BY tl.id,
tl.datetime,
tl.subject,
tl.createdby,
tl.toreceipientid,
tl.status) t
WHERE t.indexing BETWEEN @p2 AND (@p2+@p3)
... но если вы все еще получаете дубликаты, проверьте логику в SELECT / UNION в предложении WITH.
Перед тем как превратить его в динамический SQL, заставьте его работать как обычный SQL.
2) Запрос не защищен от атак с использованием инъекций, поскольку вы не обрабатываете одинарные кавычки, когда пользователи могут предоставить текст:
IF LEN(@p_SortExpression)=0
SET @p_SortExpression ='DateTime DESC'
... должно быть:
IF LEN(@p_SortExpression)=0
SET @p_SortExpression ='DateTime DESC'
ELSE
SET @p_SortExpression = REPLACE(@p_SortExpression, '''', '''''')