2014-08-27 2 views
1

SQL 결과 집합을 최대 행 수의 배치로 분할해야합니다. 이것은 75M + 행이있는 테이블에서 벗어나 Excel 또는 While 루프를 사용하는 것과 같은 많은 "간단한"해결 방법이 작동하지 않을 것입니다.배치 SQL 서버 결과 최대 행 수

다음 의지 설정 예 :

BatchId TeamPersonId TeamId PersonId 
1    1    1 101 
1    6    2 101 
1    11    3 101 
1    16    4 101 
1    21    5 101 
2    22    5 102 
2    17    4 102 
2    12    3 102 

규칙이 경우 :

SELECT DENSE_RANK()OVER (ORDER BY PersonId) as BatchGroupId, * 
FROM TeamPersonMap ORDER BY PersonId 

이 결과 집합이 될 것입니다 :

CREATE TABLE [dbo].[TeamPersonMap](
[TeamPersonId] [int] IDENTITY(1,1) NOT NULL, 
[TeamId] [int] NOT NULL, 
    [PersonId] [int] NOT NULL 
) 
GO 

DECLARE @itemCount int = 0 

WHILE (@itemCount < 5) 
BEGIN 
    SET @itemCount = @itemCount + 1 
    DECLARE @personId int = 100 
    WHILE (@personId < 105) 
    BEGIN 
     SET @personId = @personId + 1 
     INSERT INTO TeamPersonMap (TeamId, PersonId) VALUES (@itemCount, @personId)    
    END 
END 

이제 우리는 다음 쿼리를 실행할 수 있습니다 최대 배치 크기가 3이고 PersonId가 다음과 같은 최종 BatchId를 얻기 위해 쿼리해야하는 동일해야 함 다음과 같습니다. personid에 의해 분할

BatchId TeamPersonId TeamId PersonId 
1    1    1 101 
1    6    2 101 
1    11    3 101 
2    16    4 101 
2    21    5 101 
3    22    5 102 
3    17    4 102 
3    12    3 102 

답변

1

먼저 사용 ROW_NUMBER는 새로운 personid가 발생 될 때마다 1로 다시 재설정 각 행에 대해 순위를 얻을 수 있습니다. 그런 다음 3 (또는 배치 크기에 대해 원하는 숫자)로 나누고 floor 함수를 사용하여 결과 숫자를 정수로 평평하게 만듭니다. 이제 각 행에 배치 ID가 있지만 새 personID에 도달하면 다시 1로 재설정되므로 완료되지 않았습니다. personid와 새 "batchid_person_specific"열에 더한 dense_rank()를 수행하고 모든 행에 대한 전역 배치 ID를 얻을 수 있습니다. 여기

는 SQL 바이올린 : http://sqlfiddle.com/#!6/3c75d/18

결과는 다음과 같습니다

with qwry as (
SELECT 
ROW_NUMBER() OVER (PARTITION BY PersonId order by TeamPersonId) as rownum_nofloor 
, floor((ROW_NUMBER() OVER (PARTITION BY PersonId order by TeamPersonId)-1)/3)+1 as batchid_person_specific 
, * 
FROM TeamPersonMap 
) 
select 
DENSE_RANK() OVER (ORDER BY PersonId, batchid_person_specific) as BatchGroupId_Final 
,* from qwry 
ORDER BY PersonId 

[결과] [2] : 당신의 도움에 대한

| BATCHGROUPID_FINAL | ROWNUM_NOFLOOR | BATCHID_PERSON_SPECIFIC | TEAMPERSONID | TEAMID | PERSONID | 
|--------------------|----------------|-------------------------|--------------|--------|----------| 
|     1 |    1 |      1 |   1 |  1 |  101 | 
|     1 |    2 |      1 |   6 |  2 |  101 | 
|     1 |    3 |      1 |   11 |  3 |  101 | 
|     2 |    4 |      2 |   16 |  4 |  101 | 
|     2 |    5 |      2 |   21 |  5 |  101 | 
|     3 |    1 |      1 |   2 |  1 |  102 | 
|     3 |    2 |      1 |   7 |  2 |  102 | 
|     3 |    3 |      1 |   12 |  3 |  102 | 
|     4 |    4 |      2 |   17 |  4 |  102 | 
|     4 |    5 |      2 |   22 |  5 |  102 | 
|     5 |    1 |      1 |   3 |  1 |  103 | 
|     5 |    2 |      1 |   8 |  2 |  103 | 
|     5 |    3 |      1 |   13 |  3 |  103 | 
|     6 |    4 |      2 |   18 |  4 |  103 | 
|     6 |    5 |      2 |   23 |  5 |  103 | 
|     7 |    1 |      1 |   4 |  1 |  104 | 
|     7 |    2 |      1 |   9 |  2 |  104 | 
|     7 |    3 |      1 |   14 |  3 |  104 | 
|     8 |    4 |      2 |   19 |  4 |  104 | 
|     8 |    5 |      2 |   24 |  5 |  104 | 
|     9 |    1 |      1 |   5 |  1 |  105 | 
|     9 |    2 |      1 |   10 |  2 |  105 | 
|     9 |    3 |      1 |   15 |  3 |  105 | 
|     10 |    4 |      2 |   20 |  4 |  105 | 
|     10 |    5 |      2 |   25 |  5 |  105 | 
+0

감사합니다,이 위대한 -을 완벽하게 작동합니다! SQL을 행복하게 만들기 위해'with '문 앞에 세미콜론을 추가했습니다 - SQL Fiddle은 상관하지 않지만 SSMS 2008은 특정 시간에 보이는 것 같습니다. – Nicknow

+0

문제 없습니다. 세미콜론은 시작 부분이 아닌 SQL 문 끝에서 시작하므로 세미콜론 문제는 같은 워크 시트에 끝나는 세미콜론이없는 이전 SQL 문이 있음을 의미합니다. – ivanatpr