Использование результата агрегата из группы верхнего уровня внутри группы нижнего уровня - PullRequest
1 голос
/ 12 мая 2011

У меня есть 2 таблицы A {int id, int grp}, B {int aid, int cat}.

Таблица B содержит список категорий, к которым относится запись таблицы A, поэтому B.aidВнешний ключ, который ссылается на A.id.

A.id - уникальный первичный ключ таблицы A.

B.cat содержит номер категории от 1 до 5, A.grp содержит числа от 1 до1000.

Таблица A содержит 3 миллиона записей, таблица B - около 5 миллионов.

Для каждой группы A.grp мне нужно рассчитать% записей в A, которые содержат B.cat outколичества записей в группе A.grp.

Так что если A: [{1,1}, {2,1}, {3,2}], B: [{1,3}, {1,4}, {2,3}, {3,4}], тогда результатом запроса должна быть следующая таблица из 3 столбцов: R {int grp, int cat, double процент}: [{1,3,100}, {1,4,50}, {2,4,100}]

Как я могу сделать это с одним единственным запросом в Linq?

Желательно, чтобы A появлялся только один раз в этом запросе, потому чтоЯ хочу иметь возможность заменить A на A.Where (e => некоторое сложное выражение), не дублируя его много раз в этом пении.le query.

Таблицы A и B импортируются в Linq для сущностей с внешними ключами, чтобы можно было ссылаться на from a in A from b in a.B select b.cat или from b in B select b.A.grp

Ответы [ 2 ]

1 голос
/ 13 мая 2011

Вы можете объединить ваши запросы, как это

var query = from g in 
              (from a in db.A
               group a by new
               {
                 grp = a.grp
               }
              )
            join c in  
              (from a in db.A
               from b in a.B
               group b by new
               {
                 a.grp,
                 b.cat
               }
              )            
            on g.Key.grp equals c.Key.grp
            select new
            {
              g.Key.grp,
              c.Key.cat,
              percent = c.Count() * 100 / g.Count()
            };
1 голос
/ 13 мая 2011

Вот код SQL, который генерирует желаемый результат:

with grp as (select a.grp,cnt=count(*) from a group by a.grp)<br> ,cat as(select a.grp,b.cat,cnt=count( * ) * 100/grp.cnt<br> from a<br> join b on b.aid=a.id<br> join grp on grp.grp=a.grp<br> group by a.grp,b.cat,grp.cnt)<br> select * from cat

Вот код Linq, который генерирует желаемый результат:

var grp=
        from a in db.A
        group a by new{grp=a.grp}
        ;

var cat=
        from a in db.A
        from b in a.B
        group b by new{a.grp,b.cat}
        ;

var q=from g in grp
        join c in cat on g.Key.grp equals c.Key.grp
        select new{g.Key.grp,c.Key.cat,percent=c.Count()*100/g.Count()};

Но было бы неплохочтобы получить что-то вроде этого:

from a in db.A
group a by new{grp=a.grp} into grp
from g in grp
from c in g.B
group c by new{gcnt=grp.Count(),c.cat} into cat
from c in cat
select new{c.A.grp,c.cat,cnt=cat.Count()*100/cat.Key.gcnt}

Но это дает мне следующее исключение времени выполнения: Вложенный запрос не поддерживается.Operation1 = 'GroupBy' Operation2 = 'MultiStreamNest' "

...