database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
PostgreSQL
Firebird
Oracle
Informix
Sybase
ㆍMS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
MS-SQL Q&A 6621 게시물 읽기
No. 6621
이런 쿼리가 가능한가요?
작성자
초보
작성일
2013-01-21 14:54
조회수
8,161

 요즘 통계페이지를 만들고 있는데 쿼리가 너무 어렵네요.

이번에 보여줘야 되는건 

날짜                    아이디    레벨

2013-01-01      AA               1

2013-01-01     AA                2

2013-01-02     AA                2

2013-01-03       AA              3

2013-01-10         AA             4

 

이렇게 데이타가 있다면 검색 조건으로 날짜를 지정해서 2013-01-01 ~ 2013-01-10

결과값은

2013-01-01   AA  2

2013-01-02   AA   2

2013-01-03  AA   3

 

2013-01-04   AA  3

2013-01-05   AA 3

2013-01-06   AA 3

2013-01-07  AA 3

2013-01-08 AA  3

2013-01-09  AA  3

2013-01-10 AA  4

이렇게 각 날짜의 최고 레벨이 찍히면서 중간에 없는 값들은 다음 데이타가 나오기전까지 이전 값들을 찍어줘야 됩니다.

어떻게 해야 되는지 힌트라도 좀 부탁 드립니다.

 

 

 

 

 

이 글에 대한 댓글이 총 3건 있습니다.

 WITH gOrg( 날짜, 아이디, 레벨 )

AS
(
SELECT '2013-01-01', 'AA', 1 UNION ALL
SELECT '2013-01-01', 'AA', 2 UNION ALL
SELECT '2013-01-02', 'AA', 2 UNION ALL
SELECT '2013-01-03', 'AA', 3 UNION ALL
SELECT '2013-01-10', 'AA', 4
)
, gl( 날짜, 아이디, 레벨 )
AS
(
-- (1) 아이디가 2개 이상 있으면 잘 동작하지 않을 게 뻔해서... AA만 골라냄
-- 대충 짜놓고 나서 문제를 발견하고 주어진 예제가 AA 밖에 없었던 핑계를 살짝 탓해보며... 별로 고치고 싶지 않.. T,.T;;
SELECT 날짜, 아이디, 레벨
FROM gOrg
WHERE 아이디 = 'AA'
)
, aaa ( eday, 아이디, 날짜, dayMaxLvl )
AS
(
SELECT *
FROM (
-- (6) 최초일(5)에 범위(4)만큼 각각 더해서 전체 기간에 대한 각각 날짜 구하기
SELECT DATEADD( DAY, num-1, glmd.minDay ) AS eday
FROM
(
-- (5) 최초일 구하기
SELECT MIN( gl.날짜 ) AS minDay
FROM gl
) AS glmd
CROSS JOIN
(
-- (2) 최초일과 끝일 간격 알아내기
SELECT DATEDIFF( DAY, MIN( 날짜 ), MAX( 날짜 ) ) AS rdays
FROM gl
) AS rng
INNER JOIN -- (4-1) (2)로 구한 범위만큼 숫자를 (3)에서 뽑기
(
-- (3) 대략 천여개쯤 되는 숫자 생성. 설마 부족하면 sys.all_columns와 cross join으로 수백만대로 늘리기
SELECT ROW_NUMBER() OVER ( ORDER BY ( SELECT NULL ) ) AS num
FROM sys.all_columns
) AS nums ON rng.rdays + 1 >= nums.num -- (4-2) 시작날과 끝날을 모두 포함시키기 위한 + 1
) AS eachDay
LEFT OUTER JOIN -- (8) 주어진 기간 내에 있는 각각의 날짜(6)에 대해 결정할 수 있는 최대 레벨(7)을 구하기
-- (7) 날짜별 최대 레벨 구하기
SELECT 아이디, 날짜, MAX(레벨) AS dayMaxLvl
FROM gl
GROUP BY 아이디, 날짜
) AS glMaxLvl ON eachDay.eday = glMaxLvl.날짜
)
-- 위의 CTE까지 됐으면 다음의 SELECT문을 주석을 풀고 어디까지 구했는지 확인 (확인시 주석 아래의 SELECT까지 실행하면 오류나므로 주석을 푼 SELECT만 실행)
-- SELECT * FROM aaa;
-- 확인 했으면 다시 주석 달아 놓기
 
-- (9) 이빨빠진 즉, 아이디와 레벨이 NULL인 애들은 해당 날짜로부터 가장 최근의 레벨을 심어주기 위해 self-join
-- 이때 조인 조건은 나랑 날짜가 같거나 짝은 모든 애들
-- 안 돌려봤지만 join하지 않고 나랑 같거나 작은 애들 중에서 최대 값을 구해오는 subquery가 성능이 더 좋을 쑤도 있음.
-- 그래봐야 사람이 올릴 수 있는 레벨이 수백개가 최대일테니 뭐 걍 무시해도...
SELECT aa.eday, bb.아이디, MAX( bb.dayMaxLvl ) AS 그날최고레벨
FROM aaa as aa
INNER JOIN aaa as bb on aa.eday >= bb.날짜 
GROUP BY aa.eday, bb.아이디
ORDER BY aa.eday
;
 
우욱님이 2013-01-21 23:13에 작성한 댓글입니다. Edit

 감사합니다~

생각대로 무지 복잡하네요.

초보님이 2013-01-22 12:42에 작성한 댓글입니다. Edit

 1990년부터

2190년까지 100년이라고 해봐야 꼴랑 36500여 행 밖에 안되는 '날짜뻥' 테이블이 없어서 저 X랄 한거지 

'숫자뻥', '날짜뻥' 테이블은 하나정도 만들어주시면 참 편하죠..ㅋㅋ

우욱님이 2013-01-22 15:35에 작성한 댓글입니다.
이 댓글은 2013-01-22 15:35에 마지막으로 수정되었습니다. Edit
[Top]
No.
제목
작성자
작성일
조회
6624SQL 2000 Client 에서 백업하기 [5]
김우성
2013-01-24
9703
6623MDF 파일명은 어떻게 바꾸나요? [2]
김우성
2013-01-23
9697
6622파일그룹에 관련 궁금한점이 있습니다. [1]
곰보
2013-01-22
7626
6621이런 쿼리가 가능한가요? [3]
초보
2013-01-21
8161
6620마지막날의 데이타만 보고 싶을때 [1]
초보
2013-01-18
7370
6619연속된 날짜 출력하기 [1]
한동
2013-01-17
8801
6618T-SQL -> ANSI-SQL-92 변환 및 개념 문의.. [3]
서동훈
2013-01-16
9177
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.020초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다