3

誰でも助けることができますか?

基本的にはメンバーを保持し、そのクラス内にはリストがあります。

私がリストに持っているメンバーも...基本的には次のようになります。

私には 2 人のメンバーがいて、各メンバーは多数のセッションを持っています。

各メンバーを 1 つのセッションでのみ返却したいと考えています。

私はLINQクエリを実行しましたが、もちろんうまくいきません...

自己結合を行う必要があると思いますが、アイデアはありますか?

基本的に私のエラーは、サブクエリの自己結合に m が存在しないことです。

var sessions =  
from m in this.members                     
join s in
(
    from se in m.Sessions
    group se by se.Name into g
    select new {Name = g.Key, SessioEndTime = g.Max(a=>a.SessioEndTime)}
)   
on m.Name equals s.Name                    
select new { MemberName = m.Name, SessionTime = s.SessioEndTime}

誰でもフィードバックをいただければ幸いです。

前もって感謝します。

編集

次のようにできましたが、これが最善の方法ですか?

var sessions =  
from m in this.members                     
let sn = m.Sessions.OrderByDescending(a => a.SessionEndTime).FirstOrDefault()                
select new { MemberName = m.Name, SessionTime = sn.SessioEndTime}

このようにsnには1つのレコードが含まれていますが、すべてのプロパティにアクセスできます...

しかし、これが LET を使用する最善の方法でしょうか?

ありがとう。

4

1 に答える 1

5

私が何か不足していない限り、これが必要ですよね?

var sessions = 
   from m in members
   select new { 
      MemberName = m.Name, 
      SessionTime = m.Sessions.Max(s => s.SessioEndTime)
   };

LINQ クエリについての考え方を変える必要があります。SQL の実装ポイントからではなく、オブジェクト ポイントから考える必要があります。何が必要なの?すべてのメンバーが必要で、それぞれに最新のセッション終了時間があり、それに基づいて行動します。

編集: 使用した let オプションは問題ありません。FirstOrDefaultメンバーにセッションの空のリストがあり、sn.SessionEndTime が null 参照にヒットした場合、null が返されることに注意してください。一方、すべてのメンバーが少なくとも 1 つのセッションを使用していることが確実な場合は、First代わりに使用するか、集計します。また、let で使用しないでくださいFirstOrDefault()。LINQ が台無しになり、マスターに関連付けられなくなります (マスターごとに個別の SQL クエリが不足しているサブセットを検出する原因となります)。そのため、let で使用できるクエリは次のとおりです。

from m in Members                     
let sn = m.Sessions.Max(s => s.SessioEndTime)                
select new { MemberName = m.Name, SessionTime = sn};

from m in Members                     
let sn = m.Sessions.OrderByDescending(a => a.SessioEndTime).First()              
select new { MemberName = m.Name, SessionTime = sn.SessioEndTime};

順序と最大集計に関しては、両方のクエリがサブクエリを生成します。

-- MAX    
SELECT [t0].[Name] AS [MemberName], (
    SELECT MAX([t1].[SessioEndTime])
    FROM [Session] AS [t1]
    WHERE [t1].[memberId] = [t0].[id]
    ) AS [SessionTime]
FROM [Member] AS [t0]
GO

-- ordering
SELECT [t0].[Name] AS [MemberName], (
    SELECT [t2].[SessioEndTime]
    FROM (
        SELECT TOP (1) [t1].[SessioEndTime]
        FROM [Session] AS [t1]
        WHERE [t1].[memberId] = [t0].[id]
        ORDER BY [t1].[SessioEndTime] DESC
        ) AS [t2]
    ) AS [SessionTime]
FROM [Member] AS [t0]

SessioEndTime に降順のインデックスを使用すると、順序付けスクリプトは約 2 倍遅くなり (これらの実行計画を取得して自分で確認できます)、インデックスを使用しない場合は約 5 倍遅くなります。

于 2011-02-17T10:23:45.007 に答える