안녕하세요! MSSQL과 C#으로 제조업체 현장 및 관리화면 개발하는 신입개발자 입니다!
밑에와 같은 사진처럼 테이블 조회를 해야하는데요 (실제 테이블 구조와 동일하게 만들었습니다)
[질문 배경]
기존 테이블 같은 경우에는 단순 조회로
SELCT ~ FROM WHERE 문으로 JOIN해서 실행하였습니다.
변경결과테이블을 위해 제가 생각한 방법은 총 두가지였는데요
1. 동적 PIVOT
2. 동적 CURSOR
동적으로 쿼리를 생성하는 이유는
1. 학번에 따라 조회될 학생이 다름
2. 학생별 입시 항목 개수별로 COLUMN이 생성되어야함
입니다.
[쿼리 질문]
1. 동적 PIVOT
기존에 열로 가지고 있던 컬럼을 행으로 바꾸기위해 사용했지만 피벗대상컬럼안에 들어갈 컬럼이 4개가 들어가야하므로
방법을 몰라서 하다가 멈췄습니다.
2. 동적 CUSOR
입시항목 개수별로 COLUMN이 생성되어야 하므로
조회되어야 할 [입시방법, 원서접수,원서비,결과]컬럼을 SET해주었습니다.
DECLARE @QUERY varchar(MAX) = 'SELECT '
SET @QUERY = @QUERY + '학번= ' + '''' + @학번+ ''''
DECLARE CUR CURSOR FOR
SELECT 학생이름
,입학일자
,졸업일자
, 평균성적
, 출석일
, 담임이름
, 입시항목
, 입시방법
, 원서접수
, 원서비
, 결과
FROM 학생테이블
JOIN 대학테이블
WHERE 입학일자 >= '2015-01-01'
OPEN CUR
FETCH NEXT FROM CUR INTO @학생이름, @입학일자, @졸업일자, @평균성적, @출석일, @담임이름, @입시항목,@입시방법, @원서접수, @원서비, @결과
WHILE @@FETCH_STATUS = 0
BEGIN
SET @QUERY = @QUERY + ', ' + @학번 + '_학생이름 = ' + '''' + ISNULL(@학생이름, '') + ''''
SET @QUERY = @QUERY + ', ' + @학번 + '_입학일자 = ' + '''' + ISNULL(@입학일자, '') + ''''
SET @QUERY = @QUERY + ', ' + @학번 + '_졸업일자 = ' + '''' + ISNULL(@졸업일자, '') + ''''
SET @QUERY = @QUERY + ', ' + @학번 + '_평균성적 = ' + '''' + ISNULL(@평균성적, '') + ''''
SET @QUERY = @QUERY + ', ' + @학번 + '_출석일 = ' + '''' + ISNULL(@출석일, '') + ''''
SET @QUERY = @QUERY + ', ' + @학번 + '_담임이름 = ' + '''' + ISNULL(@담임이름, '') + ''''
SET @QUERY = @QUERY + ', ' + @학번 + '_입시항목 = ' + '''' + ISNULL(@입시항목, '') + ''''
SET @QUERY = @QUERY + ', ' + @학번 + '_입시방법 = ' + '''' + ISNULL(@입시방법, '') + ''''
SET @QUERY = @QUERY + ', ' + @학번 + '_원서접수 = ' + '''' + ISNULL(@원서접수, '') + ''''
SET @QUERY = @QUERY + ', ' + @학번 + '_원서비 = ' + '''' + ISNULL(@원서비, '') + ''''
SET @QUERY = @QUERY + ', ' + @학번 + '_결과 = ' + '''' + ISNULL(@결과, '') + ''''
FETCH NEXT FROM CUR INTO @학생이름, @입학일자, @졸업일자, @평균성적, @출석일, @담임이름, @입시항목,@입시방법, @원서접수, @원서비, @결과
END
CLOSE CUR
DEALLOCATE CUR
SELECT @QUERY
EXEC(@QUERY)
이렇게 했을 때에 VARCHAR(MAX)용량이 초과되어 조회되지 않습니다 ㅜㅜ
CURSOR가 필요한 컬럼은 정작 [입시항목, 입시방법, 원서접수, 원서비, 결과]뿐이고
이 컬럼들만 CURSOR로 조회할 시 데이터가 잘 받아집니다.
하지만 [학생이름, 입학일자, 졸업일자, 평균성적, 출석일, 담임이름]의 데이터조회는 되지 않고
쿼리를 모드로 나눠서 파라미터로 view단에 받아오니 동일한 controlview를 사용하기 때문에
코드상에서 쿼리를 담은 table하나는 묻히게 되어 결과가 제대로 나오지 않는 상황입니다..
정적쿼리로 무식하게 때려 박을 수 있지만 언제든 입시항목은 늘어날 수 있는 상황이기 때문에 그때 그때마다
쿼리를 수정하기 어렵다고 판단되어 동적 쿼리를 고집하고 있는 상황입니다.
분명히 방법이 있을 것 같은데 도저히 모르겠어서 2주동안 구글링하고 찾아봐도 못찾겠어서 커뮤니티에 질문올립니다!!
1. CURSOR를 돌리면서 SELECT문을 따로 함께 사용할 수 있는 방법이 있을까요?2.
2. 아니면 PIVOT으로 해결할 수 있는 방법이 있을까요?
3. 그도 아니면 다른 방법이 있으시면 꼭좀 알려주시기를 부탁드리겠습니다 !!
Comment 1
-
지영아빠
2022.03.07 10:23
피벗이라기 보다는... 테이블을 동적으로 하고자 하는 것 같은...
참고하십셔
-- with tmp as (
-- select 'A' 학생이름, '2017-03-02' 입학일자, '2020-02-15' 졸업일자, 99.5 평균성적 , 285 출석일, 'AB' 담임이름, '서울대' 입시항목, '정시' 입시방법, 'OK' 원서접수, 50000 원서비, '합격' 결과 union all
-- select 'A' 학생이름, '2017-03-02' 입학일자, '2020-02-15' 졸업일자, 99.5 평균성적 , 285 출석일, 'AB' 담임이름, '서울대' 입시항목, '수시' 입시방법, 'OK' 원서접수, 50000 원서비, '합격' 결과 union all
-- select 'B' 학생이름, '2015-03-02' 입학일자, '2018-02-15' 졸업일자, 56.5 평균성적 , 260 출석일, 'BC' 담임이름, '부경대' 입시항목, '수시' 입시방법, 'OK' 원서접수, 55000 원서비, '합격' 결과 union all
-- select 'C' 학생이름, '2014-03-02' 입학일자, '2017-02-15' 졸업일자, 98.7 평균성적 , 280 출석일, 'CD' 담임이름, '서울대' 입시항목, '정시' 입시방법, 'OK' 원서접수, 55000 원서비, '합격' 결과 union all
-- select 'D' 학생이름, '2019-03-02' 입학일자, '2022-02-15' 졸업일자, 85.4 평균성적 , 267 출석일, 'DE' 담임이름, '고려대' 입시항목, '수시' 입시방법, 'OK' 원서접수, 55000 원서비, '합격' 결과 union all
-- select 'D' 학생이름, '2019-03-02' 입학일자, '2022-02-15' 졸업일자, 85.4 평균성적 , 267 출석일, 'DE' 담임이름, '고려대' 입시항목, '정시' 입시방법, NULL 원서접수, NULL 원서비, NULL 결과
-- )
-- select * into test from tmp
-- 학번대신 이름으로
declare @nm varchar(10) = 'A'
declare @info varchar(max) = 'SELECT '
declare @cinfo varchar(max) = ''
-- 기본정보
select @info += '''' + 학생이름 + ''' 이름, ''' + 입학일자 + ''' 입학, ''' + 졸업일자 + ''' 졸업, ' + cast(평균성적 as varchar) + ' as 성적'
from (
select distinct 학생이름, 입학일자, 졸업일자, 평균성적, 출석일, 담임이름 from test where 학생이름 = @nm
) x
-- 대학정보
select
@cinfo = string_agg(convert(varchar(max), c), ',')
from
(
select
'''' + 입시항목 + ''' 입시항목_' + cast(no as varchar)+
', ''' + 입시방법 + ''' 입시방법_' + cast(no as varchar)+
', ''' + 원서접수 + ''' 원서접수_' + cast(no as varchar)+
', ' + cast(원서비 as varchar) + ' 원서비_' + cast(no as varchar)+
', ''' + 결과 + ''' 결과_' + cast(no as varchar)+ '' as c
from
(
select row_number() over(order by idx asc) no, 입시항목, 입시방법, isnull(원서접수, '') 원서접수, isnull(원서비, -1) 원서비, isnull(결과, '') 결과 from test where 학생이름 = @nm
) x
) y
exec( @info + ',' + @cinfo)