6

私の会社には 0 から n の部門があり、1 つの部門には 0 から n のオフィスがあり、1 つのオフィスには 0 から n の従業員がいます。部門ごとに従業員の平均年齢をリストするために linq を使用するクエリが必要です。は 0 です。コードは以下のとおりです。

    DataContext ctx = new DataContext();

    var q0 = from d in ctx.Departments
             join o in ctx.Offices on d.Id equals o.DepartmentId
             join e in ctx.Employees on o.Id equals e.OfficeId
             group e by d into de
             select new {
                DepartmentId = de.Key.Id,
                AverageAge = de.Count() == 0 ? 0 : de.Average(e => e.Age),
             };


    var q1 = from d in ctx.Departments
             join de in q0 on d.Id equals de.DepartmentId into des
             from de in des.DefaultIfEmpty()
             select new
             {
                 DepartmentName = d.Name,
                 AverageAge = de == null ? 0 : de.AverageAge
             };

    var result = q1.ToList();
    foreach (var item in result)
    {
        Console.WriteLine("{0}-{1}", item.DepartmentName, item.AverageAge);
    }
    ctx.Dispose();

しかし、q0 と q1 を 1 つのクエリに組み合わせるにはどうすればよいでしょうか。

4

2 に答える 2

7

次のような意味でしたか:

var newQ2 = from d in ctx.Departments
                 outer left join o in ctx.Offices on d.Id equals o.DepartmentId
                 outer left join e in ctx.Employees on o.Id equals e.OfficeId
                 group e by d into de
                 select new {
                    DepartmentId = de.Key.Id,
                    AverageAge = de.Count() == 0 ? 0 : de.Average(e => e.Age),
                 };

変更:

var newQ2 = from d in ctx.Departments
                     join o in ctx.Offices on d.Id equals o.DepartmentId
                     join e in ctx.Employees on o.Id equals e.OfficeId
                     group e by d into de.DefaultIfEmpty()
                     select new {
                        DepartmentId = de.Key.Id,
                        DepartdentName = select d.Name from d where d.id = de.Key.Id,
                        AverageAge = de.Count() == 0 ? 0 : de.Average(e => e.Age),
                     };

補遺:コードから即興で作成したデータベースレイアウトを知らずに、サブ選択を使用して追加の名前を一致させますが、より効率的にして、サブ選択に基づいてマルチパート結合を行うこともできます。申し訳ありませんが、このコードを職場でテストすることはできません。かなりうまく概算できますが、より詳細な回答が必要な場合は、部門名がどこにあるかについてさらに情報が必要です:)外側の左結合を結合に戻しました。申し訳ありませんC# で linq を使用すると、DefaultIfEmpty() を使用して、コードで外部左結合の動作を引き起こすことができることを忘れていました。

外部左結合は、対応する値がない場合は NULL を返しますが、対応する値がある部分はすべて返すことができます。ただし、参加してもnullエントリは返されません。これは、2つのクエリがあった理由だと思われますか?

私が提示したクエリに関する唯一の注意点は、値が null の場合、使用する前に必要な値を入力する必要があることです。たとえば、DepartmentId には、DE が null の場合に入力するためのロジックが必要です。

于 2012-12-19T08:18:58.313 に答える
0

みなさん、ありがとうございます。答えがわかりました。

        var q1 = 
                 from d in ctx.Departments 
                 from o in ctx.Offices.Where(o => o.DepartmentId == d.Id).DefaultIfEmpty()
                 from e in ctx.Employees.Where(e =>  e.OfficeId == o.Id).DefaultIfEmpty()
                 group e by d into de
                 select new {
                    DepartmentName = de.Key.Name,
                    AverageAge = de.Average(e => e == null ? 0 : e.Age),
                 };
于 2012-12-20T02:06:52.990 に答える