이전 기사에서 우리는 Global.asa 페이지의 특이성을 통해서 우리 사이트에 방문하는 사람들의 접속정보들을 얻어올 수 있었고, 그 데이터들을 데이터베이스에 저장할 수가 있었습니다. 이번 기사에서는 그 저장된 데이터들을 사용해서, 통계를 내어 우리가 원하는 형식으로 그 결과를 알아보기 쉽게 나타내 보려 합니다.

그동안 조금은 따분하였을지도 모르지만 그 고행(?)의 길을 묵묵히 참고 오신 분이라면 이번 기사에서 약간은 만족할(?)만한 결과를 확인하실 수가 있을 것입니다.  우리가 이번 기사에서 퉁계분석을 하고자 하는 것은 3가지 정도입니다.  물론, 더 깊이, 여러 차원에서의 통계를 낼 수도 있겠지만, 그것은 여러분의 분석력과 노력에 맞기도록 하겠습니다.

< 각 월별 >
1. 일자별 접속 통계 (최고 접속 일, 최저 접속 일)
2. 시간별 접속 통계 (최고 접속 시간대, 최저 접속 시간대)
3. 요일별 접속 통계 (최고 접속 요일, 최저 접속 요일)

먼저, 우리가 이번 기사의 결과로 마주하게 될 결과화면을 보여드리도록 하겠습니다. 그림1과 그림2를 참고해 주시기 바랍니다. 이것은 간단하게 필자가 만들어 본 것이지만, 여러분의 디자인 감각에 따라 더욱 쓸만하게 다듬으실 수 있을 것이라고 생각합니다. 그렇겠지요?


<그림 1>


<그림 2>

이전 기사에서 우리는 Statistic 이라는 테이블에 사용자들의 정보들을 기록해 두었었지요? 그 데이터들을 SQL Query Analyzer를 통해 본 결과는 그림3과 같습니다. 이것은 데이터베이스에 저장된 것을 살펴본 것이구요. 우리는 ASP를 통해서 이 데이터를 적절하게 추출해서 보기에 편하게 나타내 주어야 할 것입니다.


<그림 3>

필자가 수집한 데이터는 4월 달의 한 부분의 데이터를 수집한 것이기에 일단은 4월만의 데이터로 좁혀서 결과를 보도록 하려 합니다. 만일, 여러분의 데이터가 몇 달 정도 쌓이게 된다면 같이 할 소스 중에서 월(月)을 지정하는 변수 값만 바꾸어서 각각의 월별로 데이터를 보실 수 있을 것입니다. 그러나, 그 때는 월별 통계도 필요하겠지요? 그리고, 몇 년치의 데이터가 쌓인다면 월별, 년별의 통계치도 필요할 것이구요. 그렇습니다 통계분석은 깊이 들어가면 한도 끝도 없을 것입니다. 하지만, 여기서는 단지 특정 월(4월)들의 일별, 요일별, 시간별 통계만을 다루려 합니다. 이렇게 결정한 이유는 이 부분을 마치게 된다면, 여러분이 스스로 월별, 년별 통계는 어렵지 않게 하실 수 있을 것이라는 믿음 때문이기도 하며, 사실상 지면관계상, 그리고, 필자의 내공이 부족한 탓도 있음을 또한 인정합니다.  여러분은 예리하십니다.(T.T)

자. 이제 우리는 날짜별로의 접속 카운트를 추출해 보려 합니다.  ASP 페이지를 제작하기 전에 우리가 먼저 신경을 써야 할 것은 쿼리(Query)의 작성입니다. 현재 테이블 안에 저장되어 있는 데이터는 4월달의 데이터이기는 하지만,  날짜들은 각각 다른 상태입니다. 그렇기에 그 데이터들 중에서 각각의 날짜에 대해서 과연 몇 건의 접속이 있었는지를 파악하는 쿼리가 필요할 것입니다.

테이블 안에서 s_mon이라는 컬럼에는 해당 월이 저장되어져 있고, s_day라는 컬럼에 해당 일이 저장되어져 있습니다. 현재 우리의 관심은 s_day컬럼의 값인 "일"이지요. 각각의 날짜별로 작게는 몇십 건에서 크게는 몇천, 몇 만 건의 레코드가 저장되어져 있을 수 있습니다. 이제 이 데이터들을 "일" 로 모두 그룹을 지어서 그들의 카운터를 알아내는 쿼리를 작성해 보도록 합시다. 어떻게 작성을 하면 될까요?

다음과 같은 쿼리를 만드시면 될 것입니다.


   SELECT s_mon, s_day ,count(*) as counter FROM statistic 
   WHERE s_mon = 4
   GROUP BY s_mon, s_day < BR >    ORDER BY s_mon, s_day

     

월을 나타내는 s_mon이라는 컬럼과, 일을 나타내는 s_day라는 컬럼으로 그룹을 지어서, 각각의 카운트 값을 그룹함수인 count를 사용해서 알아오는 쿼리입니다. SQL에 대해서 어느정도 알고 계신 분들이라면 그렇게 어렵지는 않을 쿼리일 것입니다. 물론, 이 쿼리가 의미하는 바를 전혀 이해할 수 없으시다면, SQL 에 대해서 약간은(?) 공부를 하셔야 합니다. 이번 기사에 필요한 정도의 수준이라면,  기본적인 SQL 구문만을 공부하면 되는 것이기에 그것을 익히는 데는 불과 몇 시간이면 족할 것입니다. 사실 여기서 SQL문을 설명드리기는 어려울 것이기에 여러분에게 간곡히 부탁드리고자 합니다.

ASP에서 데이터베이스를 연동하고자 하시면서 기본적인 데이터베이스 언어인 SQL을 전혀 공부않는다는 것은 바람직하지 못한 자세입니다.  사실, 필자는 사이트에서 이러한 질문들을 자주 마주하고는 합니다. 바로 SQL을 왜 공부해야 하는가?에 대한 질문이지요. 여러분 스스로 느끼실 것이라고 믿습니다.

사실 ASP에서 데이터베이스를 연동하지 않을 것이라면 SQL은 공부할 필요가 없을 수도 있습니다. 그러나, ASP에서 데이터베이스를 연동하는 것은 대단히 의미있는 일이며, 비중있는 작업입니다. 그렇기에 반드시 SQL도 공부하셔야 합니다.  ASP를 하기 위해서는 HTML을 반드시 공부해야 하는 것처럼 말입니다. SQL은 이제 필수인 것 입니다. 지금이라도 공부를 시작해 주십시오. 그리고 가능하다면, SQL에 대한 지식을 습득한 후에 나머지 기사를 읽어주시기 바랍니다.

   잠깐!!   SQL과 SQL서버는 다릅니다.

   SQL은 Structed Query language라는 것으로 데이터베이스에 사용되는
   언어를 나타내며, SQL 서버는 MS의 데이터베이스 제품의 이름입니다.
   이 둘을 같은 것이라고 생각하시는 분들도 있고, 같은 의미로 사용하시는
   분들도 간혹 있는데 주의하시기 바랍니다.
   SQL 자체가 SQL 서버를 의미하는 것이 결코 아닙니다.
   이 기사에서는 SQL은 SQL이라고, SQL서버는 SQL 서버라고 확실히 지칭할 것입니다

이제(?) SQL 문에 대해서 어느 정도의 활용능력이 있는 여러분들은 위의 쿼리를 조금은 어렵지 않게 받아들이실 수 있을 것이라고 생각합니다. SQL에서 제공되는 그룹함수를 사용하기 위해 그룹함수를 지정하고자 하는 컬럼을 Group by로써 묶어주셔야 할 것입니다. 그러나, 사실상 위의 쿼리에서 추출된 데이터중 s_mon 컬럼은 우리에게 필요 없을 것입니다. 이미 우리는 '월'을 지정하고 시작하기에, 그 값은 이미 알고 있기에, 굳이 불러올 이유가 없는 컬럼입니다. 그렇기에, 실제로 우리가 사용할 쿼리는 다음과 같이 다시 정리할 수가 있습니다. (수정된 부분은 밑줄이 그어진 부분입니다) 

SELECT s_day ,count(*) as counter FROM statistic
WHERE s_mon = 4
GROUP BY s_mon, s_day
ORDER BY s_mon, s_day

WHERE s_mon = 4 라는 조건문을 둔 것은 s_mon의 값을 다른 값으로 지정하여 각각의 월의 접속현황을 얻어올 수 있게 하기 위함입니다. 세월은 빠릅니다.  기사를 잘 따라오신 분은 어쩌면 4월, 5월, 6월의 데이터들을 이미 가지고 계실지 모릅니다. 그러한 분들을 위해서 각각의 월 별로 통계를 볼 수 있게 하려고 덧붙인 것입니다. 차후 WHERE s_mon = 4 부분의 숫자를 ASP 페이지에서 변수로 지정하여 우리가 필요한 달만의 통계만을 뽑아내겠다는 것이지요. 그렇기에 필자는 이러한 쿼리를 사용하기로 결정하였습니다.

또한, 덧붙여 이야기 드리자면, 사실 s_mon이나 s_day컬럼이 없어도 같은 결과를 뽑아낼 수는 있습니다. 이미 테이블 내에는 log_time이라고 하는 날짜를 입력받은 컬럼이 있으니까요. 이 log_time 을 적절히 사용해서 같은 결과를 얻을 수가 있습니다. 해서 어쩌면 이 컬럼들(s_mon, s_day등)은 필요가 없는 컬럼들일 수 있다고 이전 기사에서 언급했었던 것이지요. 이러한 컬럼 없이도 다음과 같이 동일한 결과를 얻어내게 하는 멋진 쿼리를 작성할 수가 있으니까요. (참고, datepart함수에 대한 설명은 이 기사의 후미에 설명이 되어집니다)

select datepart(dd, log_time) , count(*) from statistic
Group by datepart(dd, log_time) order by datepart(dd, log_time)

하지만, 이 것은 대량의 레코드를 취급할 경우는 오히려 속도면에서 떨어지는  결과를 확인했습니다. 해서, 컬럼을 따로 두었던 것입니다.

1. 일자별 접속 통계 (최고 접속 일, 최저 접속 일)

자. 이제 쿼리는 준비되었습니다. 그렇다면, 이 쿼리를 바탕으로 이제 ASP 페이지를 제작해 보도록 하겠습니다. 다음에 보여드리는 ASP 페이지의 이름은 Day.asp 페이지입니다. 이 페이지의 역할은 지정한 월의 일별 접속통계를 나타내는 것입니다. 참고로 ODBC 세팅시 DSN이름은 Statistics 로 주었던 것을 기억하시지요?

Day.asp

<%
s_mon = 4 '통계를 낼 월을 지정합니다.

'데이터베이스 커넥션을 만들고 Open메소드로 연결합니다.
set dbcon = server.createObject("ADODB.Connection")
dbcon.open("DSN=Statistics;UID=계정아이디;PWD=비밀번호;")

'지정한 달의 일별 카운트를 가져오는 쿼리를 작성합니다.
sql = "select s_day ,count(*) as counter from statistic "
sql = sql & " where s_mon = " & s_mon
sql = sql & " group by s_mon, s_day"
sql = sql & " order by s_mon, s_day"

'쿼리를 실행합니다. 이제 rs라는 레코드 셋에는 우리가 원하던 데이터가 담길 것입니다.
set rs = dbcon.execute (sql)

'지정한 달의 최고 카운트수와 최저 카운트수를 저장할 변수들을 초기화 합니다.
MaxNum =0
MinNum = 100000

'레코드 셋을 루프를 돌면서 최고 카운트를 MaxNum변수에
'최저 카운트를 MinNum변수에 각각 저장합니다.
do until rs.EOF
   if rs("counter") > MaxNum then
      MaxNum = rs("counter")
   end if
   if MinNum > rs("counter") then
      MinNum = rs("counter")
   end if
   rs.movenext
loop

'다시 레코드의 위치를 첨으로 이동합니다.
rs.movefirst
%>
<html>
<head> <title><%=s_mon%> 월의 일별 접속 통계</title> </head>
<body bgcolor="#ffffff">
<center>
<table width="400">
<tr><td colspan="2" height="35">
<center><b><%=s_mon%> 월의 일별 접속 통계</b>
</td></tr>
<tr><td width="200" height="25">
<font face="돋움" size="2">최대 접속 카운트 :&nbsp;&nbsp; <b><%=MaxNum%></b></font>
</td><td width="200" align="right" height="25">
<font face="돋움" size="2">최저 접속 카운트 :&nbsp;&nbsp; <b><%=minnum%></b></font>
</td></tr>
</table> <br>
<table border="1" width="450" bordercolor="#C4EF5C" cellspacing="0" cellpadding="0">
<tr>
<td width="50" align="center"><font face="돋움" size="2">일</font></td>
<td width="100" align="center"><font face="돋움" size="2">카운트</font></td>
<td width="300" align="center"><font face="돋움" size="2">그래프</font></td>
</tr>
<%
'이제 루프를 돌면서 각각의 카운트를 출력해 줍니다.
do until rs.EOF
   s_day = rs("s_day")
   counter = rs("counter")
   '그래프로 보여줄 라인의 너비를 결정합니다.
   '너비는 각각의 카운트/최고카운트 에 3 pixel(너비用)을 곱해서 지정하였습니다.
   '이 너비는 여러분이 적절히 지정해도 좋을 것입니다.
   wid = (counter/MaxNum *100) *3
   '만일, 그 계산된 wid가 1보다 작은 경우라면 최소값으로 1을 지정합니다.
   if wid < 1 then
      wid = 1
   end if
%>
<tr>
<td align="center"><font face="돋움" size="2"
<% if counter = MinNum then %>color="red"<%end if%>
<% if counter = MaxNum then %>color="blue"<%end if%>><%=s_day%></font> </td>
<td align="right"><font face="돋움" size="2"
<% if counter = MinNum then %>color="red"<%end if%>
<% if counter = MaxNum then %>color="blue"<%end if%>><%=counter%>&nbsp; &nbsp; </font>
</td>
<td align="center">
<hr noshade size="8" color= "yellowgreen"width="<%=wid%>" align="left">
</td>
</tr>
<%
   rs.movenext
loop
%>
</table> </center>
</body>
</html>

대부분의 설명이 주석으로 소스내에 해석되어 있으므로 여러분은 어렵지 않게 그 동작하는 원리를 이해하실 것이라고 생각합니다. 여기서는 주석에서 다루지 않은 부분을 이야기 드리고자 합니다. 먼저 소스중에 ① 이라고 되어져 있는 부분입니다.

<% if counter = MinNum then %>color="red"<%end if%>...
<% if counter = MaxNum then %>color="blue"<%end if%>...

가 그것인데, 이 소스는 현재의 Loop내에서 일별 카운트가 최고카운트와 일치하면 그 출력되는 글의 색상을 파란색으로 지정하겠다는 것을 의미하구요. 현재의 Loop중의 일별 카운트가 최저카운트와 일치하면 그 출력되는 글의 색상을 붉은색으로 지정하겠다는 것을 의미합니다. 소스중의 ②는 수평 라인 태그인데요. 이것은 우리가 각각의 일별 카운트를 연산해서 얻은 수치값(wid = (counter/MaxNum *100) *3)으로 그 라인의 너비를 적절히 그려주는 코드입니다. 해서, 이 소스를 통해서 얻을 수 있는 결과화면은 다음 그림과 같습니다.

우리에게 중요한 것은 결과 수치가 제대로 나오는가?입니다.  그래프의 색상이 맘에 안든다거나, 배치구조가 맘에 안든다거나 하는 것들은 여러분이 얼마든지 시간을 가지고 이쁘게 바꿀수가 있을테니까요. 소스에서 가장 중요한 부분은 무엇일까요? 그렇습니다. 바로 쿼리부분입니다. 계속 강조드리지만 잘 구성된 최적의 쿼리야말로 가장 중요한 부분입니다. 현재 데이터가 얼마되지 않기에 그 속도의 차이를 느끼지 못하시겠지만, 저장된 데이터가 10~ 20만건, 100~200 만건 이상이 된다면 그때는 이야기가 달라질 것입니다. 한 줄의 쿼리가 그 속도를 천지차이로 바꾸기도 하니 말입니다.

여러분이 4월과 5월, 6월달의 데이터를 가지고 있다고 가정합시다. 우리의 소스중에서 단 하나만 바꾼다면. 여러분은 현재 여러분이 지정한 달의 일별 데이터를 볼 수가 있습니다. 그렇다면, 어떤 것을 바꾸면 될까요? 그렇습니다.

소스중에서 첫 번째 라인에 있는 s_mon = 4 를 적절히 수정해주면 됩니다. 5월의 데이터가 보고싶다면 s_mon = 5 라고 지정하시면 되겠지요?  여러분의 statistic 테이블에 3월의 데이터가 존재한다면,  s_mon = 3 이라고 바꾸시고 실행해 보세요. 그럼 다음과 같이 3월의 데이터를 얻으실 수가 있을 것입니다.

이전 기사에서 우리는 Global.asa 페이지의 특이성을 통해서 우리 사이트에 방문하는 사람들의 접속정보들을 얻어올 수 있었고, 그 데이터들을 데이터베이스에 저장할 수가 있었습니다. 이번 기사에서는 그 저장된 데이터들을 사용해서, 통계를 내어 우리가 원하는 형식으로 그 결과를 알아보기 쉽게 나타내 보려 합니다.

2. 시간별 접속 통계 (최고 접속 시간대, 최저 접속 시간대)

위의 일별 접속 통계를 통해서 여러분은 전체적인 구성이 약간 잡히셨을 것이라고  생각합니다. 이제부터의 시간별 접속 통계등은 위의 예를 바탕으로 약간의 변형으로 이루어지기에 그다지 어려울 것이 없을 것이라고 생각됩니다. 그러니, 편한 마음으로 같이 해 봅시다. 먼저, 시간별 접속 통계에 사용할 쿼리를 만들어 봅시다. 쿼리는 어떻게 만들며 좋을까요? 필자는 다음과 같이 작성해 보았습니다

   SELECT s_hour ,count(*) AS counter
   FROM statistic2
   WHERE s_mon = 4
   GROUP BY s_mon, s_hour
   ORDER BY s_mon, s_hour

     

먼저 월별로 그룹을 지은다음, 시간대별로 그룹을 짓습니다. 그리고, 각각의 시간과 그 카운트를 구해오는 쿼리이지요. 일별 카운트를 구해올 때와 거의 유사한 형식입니다. 그럼, 이제 이 쿼리를 사용해서 시간대 별로 접속 카운트를 구해오는 ASP 페이지를 만들어 보도록 합시다. 저의 경우 페이지의 이름을 time.asp라고 주었습니다.

time.asp

<%
s_mon = 4 '통계를 낼 월을 지정합니다.

'데이터베이스 커넥션을 만들고 Open메소드로 연결합니다.
set dbcon = server.createObject("ADODB.Connection")
dbcon.open("DSN=Statistics;UID=계정아이디;PWD=비밀번호;")

'지정한 달의 시간대 별 카운트를 가져오는 쿼리를 작성합니다.
sql = " select s_hour ,count(*) as counter from statistic "
sql = sql & " where s_mon = " & s_mon
sql = sql & " group by s_mon, s_hour "
sql = sql & " order by s_mon, s_hour "

'쿼리를 실행합니다. 이제 rs라는 레코드 셋에는 우리가 원하던 데이터가 담길 것입니다.
set rs = dbcon.execute (sql)

'지정한 달의 최고 시간대 카운트수와 최저 시간대 카운트수를 저장할 변수들을 초기화 합니다.
MaxNum =0
MinNum = 100000

'레코드 셋을 루프를 돌면서
'최고 카운트를 MaxNum변수에 '최저 카운트를 MinNum변수에 각각 저장합니다.
'그리고, 그 최고, 최저 카운트일 때의 시간대를 MaxH, MinH에 각각 저장합니다.
do until rs.EOF
    if rs("counter") > MaxNum then
        MaxNum = rs("counter")
        MaxH = rs("s_hour")
    end if
    if MinNum> rs("counter") then
        MinNum= rs("counter")
        MinH= rs("s_hour")
    end if
   rs.movenext
Loop

'다시 레코드의 위치를 첨으로 이동합니다.
rs.movefirst
%>
<html>
<head> </head>
<body bgcolor="#ffffff">
<center> <table width="450">
<tr><td colspan="2" height="35">
<center><b><%=s_mon%> 월의 시간별 접속 통계</b></center>
</td></tr>
<tr><td width="225" height="25">
<font face="돋움" size="2">최대 접속 카운트 :&nbsp;&nbsp; <b><%=maxnum%></b></font>
</td><td width="225" height="25">
<font face="돋움" size="2">최저 접속 카운트 :&nbsp;&nbsp; <b><%=minnum%></b></font>
</td></tr>
</table><br>
<table border="1" bordercolor="#FBD29B" cellspacing="0" cellpadding="0">
<tr>
<%
do until rs.EOF '이제 루프를 돌면서 각각의 카운트를 출력해 줍니다.
s_hour = rs("s_hour") '시간 값을 s_hour이라는 변수에 저장합니다.
counter = rs("counter") '시간대의 총 카운트 값을 counter라는 변수에 저장합니다.

'각 시간대별 카운트를 최고 카운트로 나누어 백분율을 낸 다음 2 pixel을 곱해줍니다.
'이미지의 사이즈를 지정하기 위한 계산입니다.
h = (counter / MaxNum*100)*2

'만일, 그 계산된 h가 1보다 작은 경우라면 최소값으로 1을 지정합니다.
if h< 1 then
  h = 1
end if
%>
<td valign="bottom" align="center" height="250" width="25">
<font face="돋움" size="2"
<% if counter = MinNum then %>color=red<%end if%>
<% if counter = MaxNum then %>color=blue<%end if%>><%=counter%></font>
<img src="orange.gif" width= "12"height="<%=h%>">
</td>
<%
rs.movenext
loop
%>
</tr>
<tr>
<%
   rs.movefirst
   do until rs.EOF  '이제 루프를 돌면서 각각의 카운트를 출력해 줍니다.
      s_hour = rs("s_hour")  '시간 값을 s_hour이라는 변수에 저장합니다.
%>
<td align="center" height="25"><font face="돋움" size="2"
<% if maxH = s_hour then%>color=blue<%end if%>
<% if minH = s_hour then%>color=red<%end if%>><%=s_hour%></font>
</td>
<%
   rs.movenext
   loop
%>
</tr>
</table></center>
</body>
</html>

시간대별 접속 카운트를 나타내는 이 소스는 이전의 일별 접속 카운트를 나타내는 소스와 비교했을 때, 사실상 큰 차이는 없습니다. 단지, 이번엔 출력되는 그래프의 모양을 가로 그래프가 아닌 수직 그래프로 사용하려 한다는 것을 제외하고는 말이지요. 그럼, 여러분들이 소스를 분석하시기에 조금은 막힐 수 있을 만한 곳을 짚어보도록 하겠습니다. 먼저, 우리의 소스중에서 만나는 첫 의문. 바로 다음과 같은 Loop 문일 것입니다.

do until rs.EOF
    if rs("counter") > MaxNum then
       MaxNum = rs("counter")
       MaxH = rs("s_hour")
       '..... 중략

이 Loop문을 보시면, 이전 일별 카운트 때와 비교했을 때, 최고 카운트를 저장하는 것 외에 MaxH와 MinH라고 하는 또 다른 변수에 값을 지정하고 있는 것을 볼 수가 있습니다. 이들이 필요한 이유는 가장 접속이 많았던 시간대와 가장 적었던 시간대가 몇 시였는지를 저장하기 위해서입니다. 그래서, 이 변수가 추가로 필요했던 것이지요. 그리고, 여기에 담긴 이 값들을 이하의 소스에서 상당히 유용하게 사용될 것입니다.

그 다음으로 소스중에 ①로 표시되어져 있는 부분을 보도록 합시다. 이것은 이전 일별 카운트때와 동일한 소스인데, Loop를 통해서 각각의 시간대별 카운트 값을 출력 해 주면서, 최고 카운트와 최저 카운트를 각각 비교하여 최고라면 파란색으로, 최저라면 빨간색으로 그 카운트를 출력하게 해주는 부분입니다.

② 부분은 <HR>대신에 이미지를 사용하기 위한 부분입니다. 이 소스에서는 결과 그래프를 세로로 보여지게 만들 것이기에 <HR>을 사용하기가 어렵습니다. 해서, 그 대안으로 사각형의 이미지를 하나 만들어, 그 이미지의 높이를 늘려주는 방식으로 처리하려 합니다. 그러므로 다음과 같은 이미지를 하나 준비해 주십시오. ( ) 사각형의 모양이면 됩니다. 색상은 자유스럽게요. 이미지의 무게를 생각해서, 이미지의 크기는 작을수록 좋겠지요?
그리고, 우리가 정한 사이즈(소스중의 h)로 그 높이를 지정해 주어서 세로방향의 그래프를 나타낼 수가 있는 것입니다. 다음 결과 그림처럼 말이지요.

이미지를 <TD>태그 안의 제일 밑에서부터 보여줄 것이기에 <TD>의 속성으로 valign="bottom"을 지정한 것을 주의하십시오. 이것을 지정하지 않으면 이미지들은 마치 음파(?)처럼 가운데로부터 정렬되어져 나타나게 될 것입니다.

 

그렇다면, ③의 역할은 무엇일까요? ③ 부분은 레코드셋을 반복해서 실행하면서 각각의 시간을 가져와 각각의 시간을 표시하는 루프를 나타냅니다. 그 시간대도 최고 시간대와 최저 시간대를 나타내기 위해서 파란색, 빨간색 처리를 한 것을 볼 수가 있습니다.

일별 통계에 비해서 소스코드가 추가되거나, 수정된 것들을 약간 있기는 합니다만,  그리 어렵지 않게 이해하실 수가 있었을 것입니다. 그렇다면, 여러분의 내공도 이해한 만큼 상승한 것입니다. 지금까지 한, 두가지의 통계를 통해 여러분은 ASP 페이지와 데이터베이스를  연동할 경우의 중요한 3가지를 깨달으셨을 것입니다.

첫 번째 : 최적화(?)된 쿼리의 작성
두 번째 : 사용자 인터페이스를 계획하기
세 번째 : ASP 페이지에 데이터베이스 연동하기(레코드셋의 루프를 통해 데이터 출력하기)

그렇습니다. 간단하게는 위의 3단계를 잘 수행하시면 크게 문제없이 여러분이 원하는 대로 페이지를 구성하실 수가 있을 것입니다. 물론, 이것도 ASP 페이지에서 사용자들에게 보여주어야 할 Spec(Specification:규격)이 커질수록, 그 구분은 세분화되어져 조금 더 정밀한 구성을 미리 기획하셔야 하겠지만 말이지요.

이제 두 가지의 통계를 내어서 결과를 마주 한 여러분들은 이 내공의 힘으로 이제 요일별 접속 카운트에 도전합니다. 여러분의 내공을 바탕으로 스스로 먼저 도전해 보십시오. 어떤가요? 머리속으로 구성이 그려지는가요? 아마도 그리 쉽게 그려지지는 않을 것 같습니다. 일단 쿼리부터도 어떻게 작성을 해야할 것인지가 선뜻 떠오르지가 않을 것입니다. 그렇다면, 우리가 사용자에게 보여주고자 하는 모습을 먼저 만나봅시다. 우리는 다음과 같은 모습으로 사용자에게 요일별 접속 카운트를 나타내고자 합니다.

 

week.asp

<%
s_mon = 4 '통계를 낼 월을 지정합니다.

'데이터베이스 커넥션을 만들고 Open메소드로 연결합니다.
set dbcon = server.createObject("ADODB.Connection")
dbcon.open("DSN=Statistics;UID=계정아이디;PWD=비밀번호;")

sql = " SELECT count(datepart(dw, log_time)) from statistic "
sql = sql & " group by datepart(dw, log_time) "
sql = sql & " order by datepart(dw, log_time) "

set rs = dbcon.execute (sql)

maxwk = 0
minwk = 100000

do until rs.EOF
    if rs(0) > maxwk then
       maxwk = rs(0)
    end if
    if minwk > rs(0) then
       minwk = rs(0)
    end if
    rs.movenext
loop

rs.movefirst
%>
<html>
<head> <title><%=s_mon%> 월의 주별 접속 통계</title> </head>
<body bgcolor="#ffffff">
<center><table width="400">
<tr><td colspan="2" height="35">
<center><b><%=s_mon%> 월의 주별 접속 통계</b></td></tr>
<tr><td width="200" align="middle" height="25">
<font face="돋움" size="2">최대 접속 카운트 :&nbsp;&nbsp; <b><%=maxwk%></b></font>
</td><td width="200" align="middle" height="25">
<font face="돋움" size="2">최저 접속 카운트 :&nbsp;&nbsp; <b><%=minwk%></b></font>
</td></tr></table><br>
<table border="1" bordercolor="#336699" cellspacing="0" cellpadding="0">
<tr>
<%
do until rs.EOF
   wk = rs(0)
%>
<td valign="bottom" align="centeR" height="250" width="50">
<font face="돋움" size="2"
<% if wk = minwk then %>color=red<%end if%>
<% if wk = maxwk then %>color=blue<%end if%> ><%=wk%></font>
<img src="grayblue.gif" width= "35"height="<%=(wk/maxwk*100)*2%>"></td>
<%
   rs.movenext
loop
%>
</tr><tr>
<td align="center" height="25" ><font face="돋움" size="2">일</td>
<td align="center" height="25" ><font face="돋움" size="2">월</td>
<td align="center" height="25" ><font face="돋움" size="2">화</td>
<td align="center" height="25" ><font face="돋움" size="2">수</td>
<td align="center" height="25" ><font face="돋움" size="2">목</td>
<td align="center" height="25" ><font face="돋움" size="2">금</td>
<td align="center" height="25" ><font face="돋움" size="2">토</td>
</tr>
</table></center>
</body>
</html>

소스를 보시면, 이번 요일별 통계는 쿼리만이 어려울 뿐, 나머지 부분은 기존 통계와 흡사함을 알 수가 있습니다. 그렇다면, 쿼리만을 따로 떼어내서 살펴보도록 합시다.

  SELECT COUNT( DATEPART(dw, log_time))
   FROM Statistic
  GROUP BY DATEPART(dw, log_time)
   ORDER BY DATEPART(dw, log_time)

      

요일별 통계를 내는 것이기에, 우리는 요일별로 그룹을 지어서 그 카운트를 가져와야 합니다. 그렇다면 어떻게 요일별로 그룹을 지을 수가 있을까요? 만일, 우리가 s_mon이나 s_day처럼 각각의 월, 일의 값을 따로 저장할 수 있는 컬럼을 두었듯이 요일의 값을 저장할 수 있는 s_week라는 컬럼을 두었다면, 이것은 이야기거리가 되지 않았을 수도 있습니다.

하지만 안타깝게도 우리는 그런 컬럼을 따로 두지는 않았습니다.  이유인즉, 여러분이 그렇게 따로 컬럼을 각각 지정하고 값을 저장하지 않아도, 이미 확보되어져 있는 log_time이라는 날짜컬럼 자체를 사용해서 이것은 모두 가능하기 때문입니다. 그럼 그 컬럼을 이용해서 어떻게 우리가 원하는 결과를 끌어낼 수가 있을까요? 먼저 모든 데이터들이 어떤 요일의 데이터인지를 알아내야 할 것입니다. 그리고, 그 요일별로 그룹을 지어야 하겠지요. 그렇다면, 각각의 데이터들의 요일을 어떻게 알아낼 수가 있을까요? DATEPART(dw, log_time)을 통해서 가능할 것입니다.

DATEPART라고 하는 SQL서버의 함수는 날짜타입의 데이터를 가지고, 우리가 지정한 날짜정보를 얻어올 수가 있게 합니다. dw 라는 인자를 사용하면,
그 데이터의 요일정보를 숫자로 가져오게 됩니다. 1부터 차례대로 일요일, 월요일 순이지요. 또한, 일자정보를 가져오려면 dd 라는 인자를 사용합니다.
(이것은 이 기사 시작부분에서 log_time를 가지고서 일별 통계를 뽑아내는 쿼리에서 사용한 적이 있었습니다) 그 이외의 인자들은 다음 표를 참고하시기 바랍니다.

Datepart 단축어
year yy, yyyy
quarter qq, q
month mm, m
dayofyear dy, y
day dd, d
week wk, ww
weekday dw
hour hh
minute mi, n
second ss, s
millisecond ms

오옷~ 여기서 정리를 하냐구요? 조금은 아쉽다구요? 안타깝게도 그렇습니다. 하지만, 이것으로 여러분들은 약간이나마 여러분의 사이트의 접속통계를 내는  방법에 대한 힌트를 얻을 수가 있었을 것입니다. 이 정보를 기반으로 더욱 세밀하게 통계를 낼 수도 있겠지요. 페이지 관계로 조금 더 깊이있는 이야기를 드리지 못함이 무척이나 저도 서운합니다. 하지만, 여기까지 오신 여러분은 이제는 스스로 길을 찾아나서실 수가 있을 것이라고 믿습니다. 어쩌면, 이번 기사의 설명이 그다지 눈에, 머리에 확 들어오지 않을지도 모르겠습니다. 뭔가 설명이 세밀하게, 자세히 설명되어지지는 못한 것 같다고 평가하실 수도 있을 것입니다. 그렇습니다. 한 회의 기사로 이것을 설명하기에는 조금은 무리가 있었던 것 같네요. 하지만, 이해가 안 가시는 부분을 조금만 더 관심있게 읽어보시며, 제공되는 소스를 보시면서 따라해 보시면 이해가 가능하시리라 믿고 싶습니다. 조금은 어렵다고 느끼실 수도 있는 내용이지만, 그러한 것을 해결했을 때의 기분은 그 어떤 것과도 바꿀 수 없는 자신만의 희열일테니까요. 이 기사와 관련된 질문은 필자의 사이트로 문의하셔도 좋습니다. 같이 고민을 나눌 여러 친구들이 있는 곳이니까요.

이 기사의 내용만으로 사이트의 완전한 접속통계를 기대하신다면 그것은 조금 어려울 것입니다. 이 기사는 여러분의 사이트의 완전한 접속통계를 보장하지는 못합니다. 단지, 그 방향성을 제시하고 있는 것이라 생각합니다. 더욱 완전한 소스는 사이트의 특성에 맞게 개발자 여러분들이 스스로  만들어 나가는 것이라고 생각하니까요. 그러면서, 그 정보를 같이 공유하며, 서로 보강해 나가는 것을 필자는 원한 답니다.

이달의 디스켓을 첨부!! (이 강좌에 사용된 소스의 다운로드)

'asp' 카테고리의 다른 글

ServerVariables 개체  (0) 2007.05.02
NIC에서 인터넷 도메인 정보 얻어오기  (0) 2007.05.02
접속자 정보 기록  (0) 2007.05.02
Global.asa와 사이트 카운터  (0) 2007.05.02
구조화된 Stored Procedure 사용법  (0) 2007.05.02

+ Recent posts