수많은 열을 행으로 만드는 방법 0 3 1,513

by 작두 [MySQL] [2022.04.28 09:25:50]


안녕하세요.

쿼리 초보자입니다. 

혼자 생각해보다 도저히 풀리지 않아 질문드립니다.

 

userId  datetime
1 2030-01-01
2 2030-02-01
3 2030-01-02
1 2030-01-02
1 2030-04-01

 위와 같은 테이블을
 

 

userId 2030-01-01 2030-01-02 2030-01-03 (생략된 날짜) 2030-04-01
1 O O X O
2 X X X X
3 X O X X

이러한 형태로 만들고 싶습니다.

 

제시된 테이블은 유저가 접속할 때마다 해당 유저 아이디와 접속 시간이 쌓이는 테이블입니다.

이 테이블을 가지고 처음 날짜부터 현재까지 유저들이 각 날짜에 접속을 했다면 O, 하지 않았다면 X으로 만들고 싶습니다.

 

처음에는 단순히 행을 열로 만들어야하다보니, CASE WHEN 을 사용하면 되겠구나 했는데 모든 날짜를 쓰기엔 어려움이 있어서요.

다음으로 고려했던 점은, 재귀 CTE로 만드는 것이었는데 재귀 CTE에는 JOIN이 되지 않고 UNION 만 되더라구요.

(초보자라 잘 몰랐습니다..)

재귀 CTE로 결과 값을 만들고 이를 다시 행을 열로 전환시켜야하는지?.. 갈피가 잘 안 잡힙니다...

 

 

어떻게 접근하면 좋을지요?

쿼리를 써주시지 않아도 아이디어나 어떠한 개념을 이용하면 되는지만 말씀해주셔도 정말 감사합니다.

좋은 하루 되세요.

by 마농 [2022.04.28 09:51:13]

모든 날짜를 다 쓰셔야 합니다.(꼭 필요하다면?)
타이핑이 귀찮으시면 엑셀 등을 활용하시면 됩니다.
결과표 양식이 과연 좋은 형식인지도 고민해 보세요.
- 조회 기간을 한정 짓는 방법 : 월간, 연간
- 하나의 컬럼에 OX 를 나열하는 방법 : OXOOXXX...
- 좀 더 간결한 형태의 화면 구성 : 일별 O/X 가 아닌 전체 접속 통계나 월간 통계 자료 제공


by 작두 [2022.04.28 18:21:30]

감사합니다! 

항상 구루비에서 마농님 글을 봤었는데 이렇게 직접 댓글을 달아주시니 뭔가 신기하네요..!

조언대로 더 직관적으로 결과를 나타낼 수 있도록 고민을 해봐야겠습니다.


by JEO [2022.04.29 10:34:50]

저도 초보라서 구현 해보고 싶어서 인터넷 검색 해서 이것 저것 한번 해봤는데 이렇게 하면 어떨까요? 

 

declare @work_dt datetime = '2030-01-01', @add_dt datetime
create table #t
( id int, dt datetime
)

insert into #t
SELECT 1 id, '2030-01-01' dt
UNION ALL SELECT 2, '2030-01-10'
UNION ALL SELECT 3, '2030-01-02'
UNION ALL SELECT 1, '2030-01-02'
UNION ALL SELECT 1, '2030-01-20'

create table #final
(id int ,dt datetime, yn char(1) )

set @add_dt = @work_dt

while @add_dt <= '2030-01-31'
begin


insert into #final
select id, dt, case when @add_dt = dt then 1 else 0 end from #t where dt = @add_dt


set @add_dt = DATEADD(day, +1, @add_dt) 
end

declare @colums nvarchar(max)
declare @sql nvarchar(max)

set @colums = ''

select @colums = @colums + '[' + yyyymmdd + '],'
from (
        select distinct
               convert(nvarchar(10), dt, 21) as yyyymmdd
               from #final where dt between @work_dt and '2030-01-31'
               ) as dt

set @colums = left(@colums, len(@colums) -1)

set @sql = '
select *
from (
select * from #final) as r
pivot ( count(yn) for dt in (' + @colums + '))
as rs
'


exec (@sql)

drop table #t
drop table #final

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입