2009-10-24 6 views
0

스키마가있는 임시 테이블이 있습니다. ID | SeqNo | 이름SQL 저장 프로 시저의 테이블에서 행 선택 및 병합

ID - 고유하지 않음
SeqNo - Int (1,2 또는 3 일 수 있음). 기본 키
이름으로 ID + SEQNO의 정렬 -이

1 | 1 | RecordA 
2 | 1 | RecordB 
3 | 1 | RecordC 
1 | 2 | RecordD 
4 | 1 | RecordE 
5 | 1 | RecordF 
3 | 1 | RecordG 

같은 테이블에있는 모든 텍스트

및 샘플 데이터는

1 | RecordA/RecordD 
2 | RecordB 
3 | RecordC/RecordG 
4 | RecordE 
5 | RecordF 

필요 같은이 테이블 출력에서 ​​선택해야합니다 커서없이이 작업을 수행 할 수 있습니다.

+1

@Johannes - 귀하의 의견을 보내 주셔서 감사합니다. 그것은 정말로 도움이되었다! !! 수천 개의 레코드가있는 테이블이있어서 고객이 원하는 형식으로 선택해야하기 때문에이 질문을드립니다. 그냥 커서가 이것에 대한 끌기라고 생각하고 어떤 아이디어라도 도움이되었을 것입니다. 샘플 데이터로 매우 명확하게 설명했기 때문에 숙제가 필요하지 않습니다. – blntechie

+0

@Johannes : 정말 중요합니까? 이것이 모두에게 이익이된다면? – Sung

답변

3

SEQNO는 1,2,3로 제한되어있는 경우 :

select id, a.name + coalesce('/'+b.name, '') + coalesce('/'+c.name, '') 
from myTable a 
left outer join myTable b on a.id=b.id and b.seqno = 2 
left outer join myTable c on a.id=c.id and c.seqno = 3 
where a.seqno = 1; 

SEQNO이 종료 열려있는 경우 재귀 CTE 배포 할 수 있습니다

;with anchor as (
    select id, name, seqno 
     from myTable 
     where seqno=1) 
, recursive as (
    select id, name, seqno 
     from anchor 
     union all 
    select t.id, r.name + '/' + t.name, t.seqno 
     from myTable t 
     join recursive r on t.id = r.id and r.seqno+1 = t.seqno) 
select id, name from recursive; 
+0

@ Remus, 버전 1에는 2 개의 자체 조인이 포함됩니다. MAX (CASE ...) GROUP BY를 사용하여 동일한 작업을 수행 할 수 있습니다. 버전 2의 경우 id 당 마지막 seqno 행 또는 MAX (이름) GROUP BY ID에 대해 재귀 적으로 필터링해야합니다. –

+0

2 개의 자체 조인 = 3 읽기 및 클러스터 된 인덱스 seqno, 그래서 3 테이블 스캔, 대 MAX (CASE ...) GROUP BY 최대 하나의 테이블 스캔을 의미합니다. –

+0

@ PeteR : 나는 당신의 솔루션이 실제로 나의 것보다 더 좋아하고 당신은 나의 업보트를 얻었지만, 성능에 관한 결론에 이르지는 마라. 세 가지 병렬 스캔 및 해시 결합을 사용하는 솔루션은 집계를위한 중간 스풀보다 빠르게 작동 할 수 있습니다. 옵티마이 저는 신비한 방식으로 작동합니다.재귀 필터에 관해서는, 재귀 부분의 조인 조건 (r.seqno + 1 = t.seqno)에 해당한다고 생각합니다. –

3

당신이 SEQNO 더 3보다 결코 알고 경우 다음 CLR UDA

select Id, Names = stuff((
    select '/'+Name from table1 b 
    where a.Id = b.Id order by SeqNo 
    for xml path ('')) 
    , 1, 1, '') 
from table1 a 
group by Id 

또는 쓰기 :

select Id, Names = stuff(
    max(case when SeqNo = 1 then '/'+Name else '' end) 
    + max(case when SeqNo = 2 then '/'+Name else '' end) 
    + max(case when SeqNo = 3 then '/'+Name else '' end) 
    , 1, 1, '') 
from table1 
group by Id 

그렇지 않으면이 같은 항목의 임의의 수에 대한 일반적인 솔루션입니다 .

편집 : 상관 된 테이블에 잘못된 별칭이 있습니다!

Edit2 : 다른 버전, Remus의 재귀 예제를 기반으로합니다. 을 선택하는 방법을 생각할 수 없었습니다. 집계 또는 정렬없이 ID 당 마지막 재귀. 아무도 몰라?

;with 
    myTable as (
    select * from (
     values 
     (1, 1, 'RecordA') 
     , (2, 1, 'RecordB') 
     , (3, 1, 'RecordC') 
     , (1, 2, 'RecordD') 
     , (4, 1, 'RecordE') 
     , (5, 1, 'RecordF') 
     , (3, 2, 'RecordG') 
    ) a (Id, SeqNo, Name) 
    )  
, anchor as (
    select id, name = convert(varchar(max),name), seqno 
    from myTable where seqno=1 
    ) 
, recursive as (
    select id, name, seqno 
    from anchor 
    union all 
    select t.id, r.name + '/' + t.name, t.seqno 
    from myTable t 
    join recursive r on t.id = r.id and r.seqno+1 = t.seqno 
    ) 
select id, name = max(name) 
from recursive 
group by id; 
---- without aggregation, we get 7 rows: 
--select id, name 
--from recursive; 
+0

+1 두 번째 예와 마찬가지로 (1,2,1을 1,1로 변경) – Andomar

0

이 솔루션은 좋은입니다. 비슷한 문제가 있지만 여기에서는 2 개의 다른 테이블을 사용하고 있습니다. 예 :

table1 

1 | 1 | 
2 | 3 | 
3 | 1 | 
4 | 2 | 
5 | 1 | 
1 | 2 | 
1 | 3 | 
4 | 1 | 
5 | 2 | 
2 | 2 | 
4 | 3 | 

table2 
1 | RecordA 
2 | RecordB 
3 | RecordC 

두 개의 테이블에서 데이터를 가져 와서 아래의 형식으로 표시하고 싶습니다.

1 | RecordA,RecordB,RecordC| 
2 | RecordB,RecordC| 
3 | RecordA | 
4 | RecordA,RecordB,RecordC| 
5 | RecordA,RecordB | 
+1

잠시 동안이 질문이 활성화되지 않았으므로 검색어에 대해 별도의 질문을 만드십시오. 여기에서 검색을하지 않으면 아무도 귀하의 질문을 지금 확인하지 않습니다. – blntechie