하나의 LINQ 쿼리에서 두 열의 가져 오기 오기
Items (ID int, Done int, Total int)라는 테이블이 가정 해 보겠습니다.
두 가지 쿼리로 수행 할 수 있습니다.
int total = m.Items.Sum(p=>p.Total)
int done = m.Items.Sum(p=>p.Done)
하지만 다음과 같은 하나의 쿼리로 수행하고 싶습니다.
var x = from p in m.Items select new { Sum(p.Total), Sum(p.Done)};
확실히 LINQ 구문에서 존재하는 함수를 호출하는 방법이 있습니다 ...?
이것은 트릭을 할 것입니다.
from p in m.Items
group p by 1 into g
select new
{
SumTotal = g.Sum(x => x.Total),
SumDone = g.Sum(x => x.Done)
};
테이블을 합산 상수로 그룹화하십시오.
from p in m.Items
group p by 1 into g
select new {
SumTotal = g.Sum(x => x.Total),
SumDone = g.Sum(x => x.Done)
}
어때
m.Items.Select(item => new { Total = item.Total, Done = item.Done })
.Aggregate((t1, t2) => new { Total = t1.Total + t2.Total, Done = t1.Done + t2.Done });
내가 생성 한 변수가 Iqueryable이라는 것을 기억할 때까지 나머지 코드에서 해결하거나 기타 혼란을 추출 할 위치를 알아내는 것이 스러웠습니다. 주문으로 구성된 테이블이 있고 ABC 회사에 대한 요약을 생성 데이터베이스에 있습니다.
var myResult = from g in dbcontext.Ordertable
group p by (p.CUSTNAME == "ABC") into q // i.e., all of ABC company at once
select new
{
tempPrice = q.Sum( x => (x.PRICE ?? 0m) ), // (?? makes sure we don't get back a nullable)
tempQty = q.Sum( x => (x.QTY ?? 0m) )
};
이제 재미있는 부분 인 tempPrice와 tempQty는 어디에도 어디에 있든 myResult의 일부 택합니다. 다음과 같이 액세스하십시오.
Console.Writeline(string.Format("You ordered {0} for a total price of {1:C}",
myResult.Single().tempQty,
myResult.Single().tempPrice ));
다른 여러 쿼리 가능 메서드도 사용할 수 있습니다.
헬퍼 튜플 클래스를 사용하여 자신의 클래스 또는 .NET 4에서 표준 클래스를 사용하여 다음을 수행 할 수 있습니다.
var init = Tuple.Create(0, 0);
var res = m.Items.Aggregate(init, (t,v) => Tuple.Create(t.Item1 + v.Total, t.Item2 + v.Done));
그리고 res.Item1
의 총이다 Total
열과 res.Item2
의 Done
열.
//Calculate the total in list field values
//Use the header file:
Using System.Linq;
int i = Total.Sum(G => G.First);
//By using LINQ to calculate the total in a list field,
var T = (from t in Total group t by Total into g select g.Sum(t => t.First)).ToList();
//Here Total is a List and First is the one of the integer field in list(Total)
이것은 이미 답변있는 다른 답변은 여전히 컬렉션에 대해 여러 반복을 수행하거나 (Sum에 대한 여러 호출) 중간 개체 / 튜플을 생성 할 경우 확장을 만들 수 있습니다. 구식 방식으로하지만 LINQ 식에 잘 맞는 메서드 (또는 다중).
이러한 확장 방법은 다음과 가변적입니다.
public static Tuple<int, int> Sum<T>(this IEnumerable<T> collection, Func<T, int> selector1, Func<T, int> selector2)
{
int a = 0;
int b = 0;
foreach(var i in collection)
{
a += selector1(i);
b += selector2(i);
}
return Tuple.Create(a, b);
}
다음과 같이 사용할 수 있습니다.
public class Stuff
{
public int X;
public int Y;
}
//...
var stuffs = new List<Stuff>()
{
new Stuff { X = 1, Y = 10 },
new Stuff { X = 1, Y = 10 }
};
var sums = stuffs.Sum(s => s.X, s => s.Y);
C # 7.0에 도입 된 튜플에 대한 언어 지원을 사용하면 다음 LINQ 식을 사용하여 문제를 해결할 수 있습니다.
var itemSums = m.Items.Aggregate((Total: 0, Done: 0), (sums, item) => (sums.Total + item.Total, sums.Done + item.Done));
전체 코드 샘플 :
var m = new
{
Items = new[]
{
new { Total = 10, Done = 1 },
new { Total = 10, Done = 1 },
new { Total = 10, Done = 1 },
new { Total = 10, Done = 1 },
new { Total = 10, Done = 1 },
},
};
var itemSums = m.Items.Aggregate((Total: 0, Done: 0), (sums, item) => (sums.Total + item.Total, sums.Done + item.Done));
Console.WriteLine($"Sum of Total: {itemSums.Total}, Sum of Done: {itemSums.Done}");
당신이 사용하는 경우 로 그룹을 Linq에이 항목이 명 컬렉션을 그래서 항목의 새 컬렉션을 만듭니다.
두 가지 문제에 대한 해결책은 다음과 같습니다.
- 한 번의 반복에서 원하는 양의 멤버 합계
- 항목의 컬렉션 복제 방지
암호:
public static class LinqExtensions
{
/// <summary>
/// Computes the sum of the sequence of System.Double values that are obtained
/// by invoking one or more transform functions on each element of the input sequence.
/// </summary>
/// <param name="source">A sequence of values that are used to calculate a sum.</param>
/// <param name="selectors">The transform functions to apply to each element.</param>
public static double[] SumMany<TSource>(this IEnumerable<TSource> source, params Func<TSource, double>[] selectors)
{
if (selectors.Length == 0)
{
return null;
}
else
{
double[] result = new double[selectors.Length];
foreach (var item in source)
{
for (int i = 0; i < selectors.Length; i++)
{
result[i] += selectors[i](item);
}
}
return result;
}
}
/// <summary>
/// Computes the sum of the sequence of System.Decimal values that are obtained
/// by invoking one or more transform functions on each element of the input sequence.
/// </summary>
/// <param name="source">A sequence of values that are used to calculate a sum.</param>
/// <param name="selectors">The transform functions to apply to each element.</param>
public static double?[] SumMany<TSource>(this IEnumerable<TSource> source, params Func<TSource, double?>[] selectors)
{
if (selectors.Length == 0)
{
return null;
}
else
{
double?[] result = new double?[selectors.Length];
for (int i = 0; i < selectors.Length; i++)
{
result[i] = 0;
}
foreach (var item in source)
{
for (int i = 0; i < selectors.Length; i++)
{
double? value = selectors[i](item);
if (value != null)
{
result[i] += value;
}
}
}
return result;
}
}
}
요약을 수행하는 방법은 다음과 같습니다.
double[] result = m.Items.SumMany(p => p.Total, q => q.Done);
다음은 일반적인 예입니다.
struct MyStruct
{
public double x;
public double y;
}
MyStruct[] ms = new MyStruct[2];
ms[0] = new MyStruct() { x = 3, y = 5 };
ms[1] = new MyStruct() { x = 4, y = 6 };
// sum both x and y members in one iteration without duplicating the array "ms" by GROUPing it
double[] result = ms.SumMany(a => a.x, b => b.y);
보시다시피
result[0] = 7
result[1] = 11
참고 URL : https://stackoverflow.com/questions/2432281/get-sum-of-two-columns-in-one-linq-query
'ProgramingTip' 카테고리의 다른 글
Lisp 웹 프레임 워크? (0) | 2020.12.04 |
---|---|
Lisp는 어떻게 언어 자체를 재정의 할 수 있습니까? (0) | 2020.12.04 |
asp.net mvc 3 면도기보기에서 reportviewer 컨트롤을 어떻게 사용할 수 있습니까? (0) | 2020.12.04 |
모듈에서 'before_save'콜백을 정의 할 수 있습니까? (0) | 2020.12.04 |
이 C ++ 코드에서 여기서 무슨 일이 일어나고 있습니까? (0) | 2020.12.04 |