2013-04-04 2 views
4

LINQ를 만드는 데 도움이 필요합니다. 일부 열이있는 표가 있지만이 문제에 관심이있는 사람은 2 명입니다.linq 선택에 도움이 필요합니다.

userid, type 

지금이 테이블이 수천 항목이 있고, 나는 단지 상단을 원의 지금까지 너무 좋아 (50)를 가정 해 봅시다,하지만 어려운 부분은 성공의 행 많은 만이 있어야하는 것입니다 1. 예

Type UserId 
============ 
Add 1 
Add 1 
Add 1 
Add 2 

로 계산 나는 단지 내가 복용하고 행의 한계에 2로 계산이 싶습니다,하지만 난 모든 행이 여전히 출력 할 싶습니다. 하나의 SQL 요청으로이 작업을 수행 할 수 있습니까? 아니면이 작업을 수행 할 다른 방법을 찾아야합니까?

편집 :이 문제를 해결할 수 있으면 값을 사용하여 테이블에 열을 추가 할 수 있습니다. Edit2가 : Sotred 절차는 또한 솔루션입니다

예 2 : 이것은 내가 지금 컴퓨터에 가까운 아니에요 그래서 내가 100 % 맞는지 확실하지 않다 3 행

Type UserId 
============ 
Add 1 
Add 1 
Add 2 
Add 1 
+2

힘들다고 생각합니다. Linq와 SQL은 순차적 인 처리가 아니라 집합 연산이 좋다. 고전적인'foreach'가 더 적합합니다. –

+0

그래,하지만 더 많은 데이터베이스에서 필요한 것을 가져오고 싶지 않다. 이론 상으로는 1000 행 이상이 시퀀스에 포함될 수있다. – Androme

+0

스토어드 프로 시저가 어렴풋이 보임. –

답변

1

LINQ에 붙어 있습니까?

PK 신원을 추가하십시오.
PK로 주문하십시오.
DataReader를 사용하여 변경 내용을 계산하십시오.
그런 다음 변경 횟수가 최대치에 도달하면 중지하십시오.

.NET 환경에 있지 않은 경우 커서로 동일한 작업을 수행하십시오.

LINQ가 지연되므로 LINQ에서 주문한 다음 ForEach에서 바로 종료 할 수 있습니다.

+0

저는 제 저장소를 고수하고 싶습니다. 그러나 이것은 최상의 해결책 일 것입니다. – Androme

+0

내 대답 업데이트보기 – Paparazzi

1

로 계산되어야한다 현명한 구문,하지만 난 당신이 이런 식으로 뭔가를 찾고 생각 :

data.Select(x => new {x.Type, x.UserId}) 
    .GroupBy(x => x.UserId) 
    .Take(50); 
+0

오랫동안 groupby와 함께 일한 적이별로 없지만 모든 항목을 1 개의 단일 항목으로 그룹화하지는 않습니까? – Androme

+0

네 말이 맞아, 내가 서로 옆에 그룹화해야한다는 다른 조건을 알지 못했다. 해결책에 대해 더 생각해보고 편집으로 돌아올 것이다. –

1

당신 Linq에 함께 할, 그러나 전통적인 for 루프보다 훨씬 속도가 느려질 수 있습니다. 한 가지 방법은 다음과 같습니다.

data.Where((s, i) => i == 0 || 
        !(s.Type == data[i-1].Type && s.UserId == data[i-1].UserId)) 

"이전"항목과 동일한 유형 및 사용자 ID가있는 "중복"항목은 건너 뜁니다.

그러나이 경우에만 data에 인덱서 (배열 또는 IList을 구현하는 항목)가있는 경우에만 작동합니다. IEnumerable 또는 IQueryable은 작동하지 않습니다. 또한 SQL로 변환 할 수 없으므로 모든 결과를 가져 와서 메모리 내에서 필터링해야합니다.

SQL에서 수행하려는 경우 값 중 하나가 변경되거나 ROW_NUMBER 열을 포함하는 공통 테이블 식을 사용하는 경우 임시 테이블을 채우고 커서를 검색 한 다음 다시 되돌리기 하위 쿼리를 수행합니다. 위의 LINQ 방법과 유사한 쿼리 : ... 당신은 LINQ 사용하여이 작업을 수행 할 수

WITH base AS 
(
SELECT 
    Type, 
    UserId, 
    ROW_NUMBER() OVER (ORDER BY ???) AS RowNum 
    FROM Table 
) 
SELECT b1.Type, b1.UserId 
FROM base b1 
LEFT JOIN base b2 ON b1.RowNum = b2.RowNum - 1 
WHERE (b1.Type <> b2.Type OR b1.UserId <> b2.UserId) 
ORDER BY b1.RowNum 
+0

이것은 이론적으로 테이블이 더 많은 수천 개의 항목을 가질 수 있기 때문에 내가 피하고 싶은 것입니다! – Androme

+0

흠, 내가 만든 SQL을 작동시킬 수는 없지만, 올바르게 읽으면 그것을 다른 값으로 돌려주지 않을까요? – Androme

+0

다음 행과 다른 행을 반환해야합니다. 마지막 행은'b2' 값이 그 시점에서 NULL이 될 것이므로 포함되어야합니다. 오류가 발생하거나 잘못된 결과가 있습니까? –

1

하지만 나는 "에 대한 (각) 루프"경로를 이동하는 것이 더 쉬울 수 있다고 생각

data.Select((x, i) => new { x.Type, x.UserId, i }) 
    .GroupBy(x => x.Type) 
    .Select(g => new 
    { 
     Type = g.Key, 
     Items = g 
      .Select((x, j) => new { x.UserId, i = x.i - j }) 
    }) 
    .SelectMany(g => g.Select(x => new { g.Type, x.UserId, x.i })) 
    .GroupBy(x => new { x.Type, x.i }) 
    .Take(50); 
    .SelectMany(g => g.Select(x => new { x.Type, x.UserId })); 
관련 문제