LINQで複数のプロパティをキーに重複を除去&子要素の先頭を取得
複数プロパティをキーに重複を除去
例として、以下のような「商品」クラスがあるとして
/// <summary>
/// 商品
/// </summary>
public class SalesItem
{
/// <summary>
/// ID
/// </summary>
[Key, Column(TypeName = "int")]
public int Id { get; set; }
/// <summary>
/// 商品コード
/// </summary>
[Column(TypeName = "nvarchar")]
public string SalesItemCode { get; set; }
/// <summary>
/// 商品名
/// </summary>
[Column(TypeName = "nvarchar")]
public string SalesItemName { get; set; }
}
商品コードと商品名で重複を除去して集計するには以下のようになる。
// LINQPadでLanguageにC# Expressionを選んでいる場合の例。
SalesItems.GroupBy(s => new { s.SalesItemCode, s.SalesItemName }).Select(g => g.FirstOrDefault()).ToList().Dump() // LINQPad上で結果を見る場合は .Dump() を追加
なんだか若干分かりにくいが、上記のようにGroupBy、Select、FirstOrDefaultを組み合わせるとできる。
どうやらIGroupingインターフェイスをFirstOrDefaultすると最初のデータが取得されるらしい。
LINQ to ObjectsでもLINQ to EntitiesでもOK。
ちなみにEntity Frameworkの場合、LINQPadでSQLを確認すると以下のようなSQLが発行されている。
SELECT
[Limit1].[SalesItemId] AS [SalesItemId],
[Limit1].[SalesItemCode] AS [SalesItemCode],
[Limit1].[SalesItemName] AS [SalesItemName]
FROM (SELECT DISTINCT
[Extent1].[SalesItemCode] AS [SalesItemCode],
[Extent1].[SalesItemName] AS [SalesItemName]
FROM [dbo].[SalesItems] AS [Extent1] ) AS [Distinct1]
OUTER APPLY (SELECT TOP (1)
[Extent2].[SalesItemId] AS [SalesItemId],
[Extent2].[SalesItemCode] AS [SalesItemCode],
[Extent2].[SalesItemName] AS [SalesItemName]
FROM [dbo].[SalesItems] AS [Extent2]
WHERE ([Distinct1].[SalesItemCode] = [Extent2].[SalesItemCode]) AND ([Distinct1].[SalesItemName] = [Extent2].[SalesItemName]) ) AS [Limit1]
※DISTINCTしたテーブルをOUTER APPLYしてSELECT TOP 1。
うーん、あんまり見慣れない感じのSQLだけど集計効率的にはどうなのだろうか・・・
子要素の先頭を取得
あるデータに子要素が複数あって1件だけ取得したい場合も同様の実装で実現できる。
以下のようなUserクラスを内包するLoginクラスがあり、同じユーザーのレコードが複数あるとして、
※Userクラスの中身は割愛
/// <summary>
/// ログイン情報
/// </summary>
public class Login
{
/// <summary>
/// ログインID
/// </summary>
[Key, Column(TypeName = "uniqueidentifier")]
public Guid LoginId { get; set; }
/// <summary>
/// ログインユーザID
/// </summary>
[Column(TypeName = "int")]
public int UserId { get; set; }
[ForeignKey("UserId")]
public User User { get; set; }
}
Userごとの1件分のLoginを取得するコードは以下のようになる。
// LINQPadでLanguageにC# Expressionを選んでいる場合の例。
Logins.GroupBy(l => l.UserId).Select(g => g.FirstOrDefault()).Dump() // LINQPad上で結果を見る場合は .Dump() を追加
Author And Source
この問題について(LINQで複数のプロパティをキーに重複を除去&子要素の先頭を取得), 我々は、より多くの情報をここで見つけました https://qiita.com/koba-a-koba/items/40c74e3d9890e53b4d22著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .