简体   繁体   English

SQL:在Linq中从x左联接y中选择SELECT id,MAX(y.DateCreated)吗?

[英]SQL: SELECT id, MAX(y.DateCreated) FROM x LEFT JOIN y in Linq?

I can't seem to rewrite this SQL into EF Linq: 我似乎无法将此SQL重写为EF Linq:

SELECT      Conversation.Id
FROM        Conversation LEFT JOIN Message
                ON  Conversation.Id = Message.ConversationId
GROUP BY    Conversation.Id
ORDER BY    MAX(Message.DateCreated) DESC

I would think something like this would work: 我认为这样的事情会起作用:

 _dbContext.Conversation
           .OrderByDescending(c => c.Messages.DefaultIfEmpty().Max(m => m.DateCreated))
           .Select(cm => cm.Id);

But this gives me the error System.InvalidOperationException : Sequence contains no elements. 但这给了我错误System.InvalidOperationException : Sequence contains no elements.

Also this: 还有这个:

_dbContext.Conversation
          .Select(c => new {c.Id, MaxDate = c.Messages.DefaultIfEmpty().Max(m => m.DateCreated)})
          .OrderByDescending(c => c.MaxDate)
          .Select(cm => cm.Id);

But that gives me System.ArgumentException : At least one object must implement IComparable. 但这给了我System.ArgumentException : At least one object must implement IComparable. .

What is the correct way to do this? 正确的方法是什么?

Can you try this: 你可以尝试一下:

from r in Conversation
              join ru in Message
              on r.Id equals ru.ConversationId into ps
              from ru in ps.DefaultIfEmpty()
              group ru by new { ru.ConversationId, ru.DateCreated } into rug
              select new {
                  id = ru.ConversationId,
                  datecreated = rug.Max(ru => ru.datecreated)
              }).OrderByDescending(x => x.datecreated);

This maynot compile as I dont have the code to test this with (like a fiddle) 这可能无法编译,因为我没有用它进行测试的代码(像小提琴一样)

You're close though, just drop DefaultIfEmpty 不过,您已经关闭,只需删除DefaultIfEmpty

_dbContext.Conversation.Select(con => new 
    {
        con.Id,
        MaxDateCreated = (DateTime?) con.Messages.Max(msg => msg.DateCreated)
    })
.OrderByDescending(con => con.MaxDateCreated)
.ToArray()

Here is what's going to get generated 这是将要生成的

SELECT 
[Project2].[C1] AS [C1], 
[Project2].[Id] AS [Id], 
[Project2].[C2] AS [C2]
FROM ( SELECT 
    [Project1].[Id] AS [Id], 
    1 AS [C1], 
     CAST( [Project1].[C1] AS datetime2) AS [C2]
    FROM ( SELECT 
        [Extent1].[Id] AS [Id], 
        (SELECT 
            MAX([Extent2].[DateCreated]) AS [A1]
            FROM [dbo].[Message] AS [Extent2]
            WHERE [Extent1].[Id] = [Extent2].[ConversationId]) AS [C1]
        FROM [dbo].[Conversation] AS [Extent1]
    )  AS [Project1]
)  AS [Project2]
ORDER BY [Project2].[C2] DESC

I believe this will generate the SQL you are looking for (plus or minus a nested sub-query): 我相信这将生成您要查找的SQL(加上或减去嵌套的子查询):

var ans = from c in Conversation
          join m in Message on c.Id equals m.ConversationId into mj
          from m in mj.DefaultIfEmpty()
          group m by c.Id into mg
          orderby mg.Max(m => m.DateCreated) descending
          select mg.Key;

However, in LINQ you can use group join instead of regular join. 但是,在LINQ中,可以使用组联接而不是常规联接。 This should also do what you want, but uses a sub-select in SQL, so I am not sure which is more efficient on the server. 这也应该做您想要的,但是在SQL中使用子选择,因此我不确定哪个在服务器上更有效。 The common wisdom seems to be join was better, but following by group by may make it moot, as may a modern enough optimizer. 普遍的想法似乎是加入更好,但是像现代足够的优化程序那样,逐个加入可能会使它变得毫无意义。 Another post I found said the sub-query (CIS) was much more efficient, so this may be better. 我发现的另一篇文章说,子查询(CIS)效率更高,所以可能更好。

var ans2 = from c in Conversation
           join m in Message on c.Id equals m.ConversationId into mj
           orderby mj.Max(m => m.DateCreated) descending
           select c.Id;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM