Разбейте его на мельчайшие компоненты, а затем составьте больший запрос из этого.Давайте начнем с самого внутреннего запроса, который имеет смысл:
SELECT
a.id, COUNT(*) AS ranknum
FROM
T_News AS a
INNER JOIN T_News AS b ON
(a.type = b.type) AND
(a.datereg >= b.datereg)
GROUP BY
a.id
HAVING
COUNT(*) <= 3
Я бы преобразовал это в:
// Items with counts/ranknum
var ranknum =
from a in News.All()
join b in News.All() on
a.type equals b.type
where
a.datereg > b.datereg
group by a.id into g
select new { g.Key as id, g.Count() as ranknum };
// Filter the ranknum.
ranknum = ranknum.Where(rn => rn.ranknum <= 3);
Затем соединил бы это с внешним запросом:
SELECT
c.type,c.title,c.datereg, d.ranknum
FROM
T_News AS c
INNER JOIN (<sub-query from above>) as d ON
c.id = d.id
ORDER BY
c.type, d.ranknum
Эта часть становится простой, поскольку это просто соединение двух существующих запросов.
var query =
from c in News.All()
join rn in ranknum on c.id = rn.id
orderby c.type, rn.ranknum
select new { c.type, c.title, c.datereg, rn.ranknum };
Скорее всего, это SQL, который LINQ-to-Entities сгенерирует для этого, будет выглядеть реально уродливо и, вероятно, будет неэффективно, в этом случае вы можете рассмотреть возможность размещения этой логики в хранимой процедуре, а затем вызывать , что через LINQ-to-Entities (что в общем случае верно для более сложных запросов).