Linq to Sql: возвращает ограниченное количество строк в группе - PullRequest
3 голосов
/ 19 января 2011

Представьте себе таблицу продуктов со следующими данными:


    ProductID    UserName   ProductName
    -----------------------------------
    1            User1      Product1
    2            User1      Product2
    3            User2      Product3
    4            User3      Product4
    5            User1      Product5
    6            User2      Product6
    7            User2      Product7
    8            User1      Product8

Также есть еще одна таблица с именем UserLimit:


    UserName    DisplayLimit
    -------------------------
    User1       3
    User2       2
    User3       2

В этой таблице указано максимальное количество товаров, которое должно быть возвращено каждому пользователю.
То, что я хочу сделать, это иметь запрос Linq to Sql, который возвращает это:


    ProductID     UserName    ProductName
    --------------------------------------
    1             User1       Product1
    2             User1       Product2
    5             User1       Product5
    3             User2       Product3
    6             User2       Product6
    4             User3       Product4

Количество продуктов, возвращаемых для каждого пользователя, ограничено значением DisplayLimit в таблице UserLimit.

Ответы [ 3 ]

3 голосов
/ 20 января 2011

Используя группирование по пользователю, вы легко можете попасть в каждую группу, содержащую нужное количество товаров.

var limitedUsers = from p in dc.Products
                   group p by p.UserName into g
                   select new
                   {
                     UserName = g.Key,
                     Products = g.Take(dc.UserLimits
                                         .Where(u => u.UserName == g.Key)
                                         .Single().DisplayLimit)
                   };
2 голосов
/ 19 января 2011

Не уверен, как ссылка на SQL будет вписываться в это, но если это возможно, вы можете попробовать использовать функцию DENSE_RANK. Например, приведенный ниже запрос вернет последние 3 проекта для каждого пользователя. Ограничение является общим для всех пользователей, но ничто не мешает ссылаться на таблицу с ограничениями.

declare @numberOfProjects int
set @numberOfProjects = 3

;with topNProjects(userid, projectid, createdtutc, dense_rank)
as (
    select p.userid, P.ProjectId, p.CreatedDtUtc, DENSE_RANK() OVER (PARTITION BY P.UserId ORDER BY P.ProjectId) AS DENSE_RANK
    from DS_Project P
)
select userid, projectid, createdtutc from topNProjects
where dense_rank <= @numberOfProjects
order by projectid desc

EDITED: попробовал решение LINQed и придумал следующее. Я думаю, все, что вам нужно сделать, это заменить мои коллекции ссылками на таблицы в контексте данных.

        Dictionary<int, string> userProjects = new Dictionary<int, string>
        {
            { 1, "User1" },
            { 2, "User1" },
            { 3, "User2" },
            { 4, "User3" },
            { 5, "User1" },
            { 6, "User2" },
            { 7, "User2" },
            { 8, "User1" },
        };
        Dictionary<string, int> limits = new Dictionary<string, int>
        {
            { "User1", 3 },
            { "User2", 2 },
            { "User3", 2 },
        };


        var ranked = 
            from up in userProjects
            join l in limits on up.Value equals l.Key
            orderby up.Value
            where (from upr in userProjects
                   where upr.Value == up.Value && upr.Key <= up.Key
                   select upr).Count() <= l.Value
            select up;

Результат выглядит следующим образом: кажется, это то, что вы ищете:

1, User1
2, User1
5, User1
3, User2
6, User2
4, User3
1 голос
/ 19 января 2011

Если запрос должен быть Linq, возможно, вам нужно что-то вроде этого:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...