2010-11-27 5 views
6

각각 순차 색인을 포함하는 행이있는 데이터베이스 테이블이 있습니다. 이 인덱스 열을 기반으로 연속적인 행 그룹을 선택하고 싶습니다. 예를 들어, 나는 다음과 같은 인덱스 값을 가진 행을했다 :엔티티에 대한 LINQ가 포함 된 연속 항목 선택

1 
3 
4 
5 
7 
9 
10 
11 
12 
15 
16 

을 나는 3 개 연속 인덱스 (이 번호는 다름) 모든 그룹을 선택하고 싶었다. 나는 다음과 같은 그룹을 얻을 것입니다 : 기본적으로

3, 4, 5 

9, 10, 11 

10, 11, 12 

을, 여기 질문에 비슷한 일을 달성하기 위해 제기하려고 해요 :

selecting consecutive numbers using SQL query

그러나, 내가 엔티티에 LINQ와이를 구현하려면 실제 SQL이 아닙니다. 나는 또한 저장 프로 시저를 사용하지 않기를 바랄 것이고 ToList/looping 접근법을 사용하고 싶지는 않을 것이다.

편집 : 요청 된 연속 요소를 초과하는 그룹이 반드시 분리 될 필요는 없습니다. 즉 이전의 예에서, 9, 10, 11, 12의 결과도 또한 허용 될 수있다.

답변

0
using (var model = new AlbinTestEntities()) 
{ 
    var triples = from t1 in model.Numbers 
        from t2 in model.Numbers 
        from t3 in model.Numbers 
        where t1.Number + 1 == t2.Number 
        where t2.Number + 1 == t3.Number 
        select new 
        { 
         t1 = t1.Number, 
         t2 = t2.Number, 
         t3 = t3.Number, 
        }; 

    foreach (var res in triples) 
    { 
     Console.WriteLine(res.t1 + ", " + res.t2 + ", " + res.t3); 
    } 
} 

using (var model = new AlbinTestEntities()) 
{ 
    var triples = from t1 in model.Numbers 
        join t2 in model.Numbers on t1.Number + 1 equals t2.Number 
        join t3 in model.Numbers on t2.Number + 1 equals t3.Number 
        select new 
        { 
         t1 = t1.Number, 
         t2 = t2.Number, 
         t3 = t3.Number, 
        }; 

    foreach (var res in triples) 
    { 
     Console.WriteLine(res.t1 + ", " + res.t2 + ", " + res.t3); 
    } 
} 

처럼 결합하지만 난 관리 스튜디오에서 결과 쿼리를 비교할 때 생성 내부를 사용하는 것이 더 나은 수 있습니다 다음과 같은 SQL을

SELECT 
[Extent1].[Number] AS [Number], 
[Extent2].[Number] AS [Number1], 
[Extent3].[Number] AS [Number2] 
FROM [dbo].[Numbers] AS [Extent1] 
CROSS JOIN [dbo].[Numbers] AS [Extent2] 
CROSS JOIN [dbo].[Numbers] AS [Extent3] 
WHERE (([Extent1].[Number] + 1) = [Extent2].[Number]) AND (([Extent2].[Number] + 1) = [Extent3].[Number]) 

를 생성 동일한 실행 계획을 세우고 정확히 같은 시간을 실행하십시오. 이 제한된 데이터 집합 만있는 경우 데이터 집합의 성능이 더 크면이를 비교할 수 있고 그 차이가 가장 큰 데이터 집합을 선택할 수 있습니다.

+0

감사합니다. 그러나 3 행만 작동하는 것처럼 보입니다. 나는 숫자가 다양해야한다. 2 연속 행이 필요하거나 20이 필요할 수 있습니다.이를 수행 할 수있는 방법이 있습니까? – knoia

0

다음 코드는 모든 "루트"를 찾습니다.

var query = this.commercialRepository.GetQuery(); 
    var count = 2; 
    for (int i = 0; i < count; i++) 
    { 
     query = query.Join(query, outer => outer.Index + 1, inner => inner.Index, (outer, inner) => outer); 
    } 

    var dummy = query.ToList(); 
당신이 다른 사람을 remeber하는 쿼리를 수정해야합니다 중 하나 또는 당신이 뿌리를 가지고 있다는 사실을 기반으로 쿼리를 만들 수 있도록

은 각 그룹의 첫 번째 항목을 찾을 것과 당신 얻을 색인을 알아야합니다. 나는 가야하기 전에 그것을 감쌀 수 있었지만 미안해. 아마 조금 도움이 될거야.

추신. 카운트가 2이면이 경우 3이라는 그룹을 찾습니다.

+0

마치 작동하는 것 같습니다.그러나 나는이 접근법에 대한 또 다른 관심사가 있습니다. 많은 조인이 성능에 좋지 않을까요? 주제에서 나는 맨 위로 대답에만 링크를 단 하나의 조인을 할 것 같았다. – knoia

+0

이 숫자를 6으로 테스트하고 약 130 개의 조인으로 감았습니다. – knoia

1

그래서 제가 링크 된 주제에서 Brian의 답변을 모델로 한 아주 좋은 솔루션을 생각해 냈습니다.

var q = from a in query 
     from b in query 
     where a.Index < b.Index 
     && b.Index < a.Index + 3 
     group b by new { a.Index } 
      into myGroup 
      where myGroup.Count() + 1 == 3 
      select myGroup.Key.Index; 

원하는 연속 행 수를 3으로 변경하십시오. 이렇게하면 모든 연속 행 그룹의 첫 번째 색인이 제공됩니다. 내가 제공하는 원래의 예에 적용, 당신은 얻을 것이다 :

3 
9 
10 
1

나는이 (비록 C#을) 꽤 효율적으로 작업 할 것 같아요 : 응답에 대한

int[] query = { 1, 3, 4, 5, 7, 9, 10, 11, 12, 15, 16 }; 
int count = 3; 
List<List<int>> numbers = query 
    .Where(p => query.Where(q => q >= p && q < p + count).Count() == count) 
    .Select(p => Enumerable.Range(p, count).ToList()) 
    .ToList(); 
+0

이것은 Linq to Objects에서 작동하지만 Linq에서 Entities로는 작동하지 않습니다. – StriplingWarrior

관련 문제