Как реализовать этот блок Sql, содержащий (Имея, Присоединиться и Группировать по) с Linq - PullRequest
1 голос
/ 03 февраля 2012

мое заявление sql

SELECT c.type,c.title,c.datereg, d.ranknum
FROM T_News AS c
  INNER JOIN (
    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
  ) AS d ON (c.id = d.id)
ORDER BY c.type, d.ranknum

что я получаю http://rickosborne.org/blog/2008/01/sql-getting-top-n-rows-for-a-grouped-query/

для получения TOP N строк для сгруппированного запроса

EFUnitOfWork EF = new EFUnitOfWork();
T_NewsRepository News = new T_NewsRepository();
News.UnitOfWork = EF;
var query = 
    from news1 in News.All()
    join news2 in News.All() 
        on news1.type equals news2.type into resjoin
    group news1 by news1.id into idgroup
    where idgroup.Count() <= 3
    select new { idgroup };

var x = query.ToList();

Я не получил никакой ошибки, но "где idgroup.Count () <= 3" не сработал, и я получил все строки в БД в результате </p>

1 Ответ

1 голос
/ 03 февраля 2012

Разбейте его на мельчайшие компоненты, а затем составьте больший запрос из этого.Давайте начнем с самого внутреннего запроса, который имеет смысл:

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 (что в общем случае верно для более сложных запросов).

...