퇴근5분전


[쿼리1.]

SELECT CNT, CASE WHEN 4 <= RET AND RET  <= 7 THEN 1 ELSE 0 END RET, CASE WHEN 6 <= [PLAN] AND [PLAN] <= 10 THEN 1 ELSE 0 END PL
FROM @TABLE
WHERE RET BETWEEN 4 AND 7  OR [PLAN] BETWEEN 6 AND 10

SELECT ISNULL(SUM( CASE WHEN RET = 1 THEN CNT ELSE 0 END ),0) RETSUM , ISNULL(SUM( CASE WHEN PL = 1 THEN CNT ELSE 0 END ),0) PLANSUM
FROM(
  SELECT CNT,  CASE WHEN 4 <= RET AND RET  <= 7 THEN 1 ELSE 0 END RET, CASE WHEN 6 <= [PLAN] AND [PLAN] <= 10 THEN 1 ELSE 0 END PL
  FROM @TABLE
  WHERE (RET BETWEEN 4 AND 7  OR [PLAN] BETWEEN 6 AND 10)  
)K

[쿼리2.]

SELECT  SA, SB
FROM
(
  SELECT 'A' [KEY], SUM( CNT ) SA
  FROM @TABLE
  WHERE RET BETWEEN 4 AND 7 
) A
INNER JOIN
(
  SELECT 'A' [KEY],  SUM( CNT ) SB
  FROM @TABLE
  WHERE [PLAN] BETWEEN 6 AND 10  
)B
ON A.[KEY] = B.[KEY]

실행계획




http://aseuka.tistory.com/entry/MS-SQL  이 글에 이어 써본다.

위 두 쿼리 결과는 동일하게  4, 5가 나온다.

다만 테이블을 1번 읽었을때와 2번읽었을때를 비교해보기 위해 이글을 써보며

아직 해당 지식이 완전하게 흡수하지 못한점을 미리 써둔다. 


일단 IO가 많이 발생하면 쿼리 개선이 필요하다고 하니... 
                               1번 쿼리                       2번 쿼리
IO 비용                 :    0.0032035                      (0.003125 * 2) 

또 마지막 결과에 대한 트리비용에 대해 확인해보자
                                1번 쿼리                       2번 쿼리 
예상 하위 트리비용 :    0.0032846                      0.0065743

Sort는 둘다 일어나지 않는다!





수치적으로 두배정도 차이나는데

2번 쿼리는 굳이 필요없는 Nested Loops 를 하고 있는 점.
동일 쿼리를 2번 행하고 있는것... 그림으로만 봐도 두배는 걸리는게 맞을것이다.

전에도 실행계획을 보다 보다 모르는게 많아서 패스 했는데

이참에 찾아서 정리해야겠다.

? Stream Aggregate
? Compute Scalar
? Nested Loops

Hash.. 어쩌고 저쩌고.. 참 많은뎁!!

















하나의 데이타 테이블에서  두개의 컬럼의 각각 범위로 조회를 한방에 해서

각각의 그룹바이를 취하는 방법...

역시 공부한 보람이 있다눈..

아래 그림에서 보다싶이 원본데이타에서

범위를 지정해서 범위내 데이타에 대해 컬럼 값을 1로 치환 하고

그 데이타를 그룹바이 걸어서 각각 값을 구하는 방법임.







declare @table  table
(
     [Cnt] int,
     [ret]  int,
     [plan] int
)

insert into @table values(1, 1, 6 );
insert into @table values(1, 2, 7 );
insert into @table values(1, 3, 8 );
insert into @table values(1, 4, 9 );
insert into @table values(1, 5, 10 );
insert into @table values(1, 6, 11 );
insert into @table values(1, 7, 12 );
insert into @table values(1, 8, 13 );


select * from @table

SELECT CNT,  CASE WHEN 4 <= RET AND RET  <= 7 THEN 1 ELSE 0 END RET, CASE WHEN 6 <= [PLAN] AND [PLAN] <= 10 THEN 1 ELSE 0 END PL
FROM @TABLE
WHERE RET BETWEEN 4 AND 7  OR [PLAN] BETWEEN 6 AND 10

SELECT ISNULL(SUM( CASE WHEN RET = 1 THEN CNT ELSE 0 END ),0) RETSUM , ISNULL(SUM( CASE WHEN PL = 1 THEN CNT ELSE 0 END ),0) PLANSUM
FROM(
  SELECT CNT,  CASE WHEN 4 <= RET AND RET  <= 7 THEN 1 ELSE 0 END RET, CASE WHEN 6 <= [PLAN] AND [PLAN] <= 10 THEN 1 ELSE 0 END PL
  FROM @TABLE
  WHERE (RET BETWEEN 4 AND 7  OR [PLAN] BETWEEN 6 AND 10)  
)K

 

훈스 닷넷에 올라온 챠트관련 질문에 답글을 달았다.

챠트 구현보다 설치하는 시간이 더 걸린...

나름 단순하면서 깔끔해보인다.

챠트 설치 파일 검색에서 챠트를 잘 정리해둔 블로그가 있어서

챠트설치파일 링크만 써봤음...
http://six605.tistory.com/431?srchid=BR1http%3A%2F%2Fsix605.tistory.com%2F431











완성된 챠트입니다.
 
 
 아래 보시면 LINQ를 이용해서 새로운 테이블을 만든것을 볼수 있는데요
 
[YM]   , [CNT1], [CNT2]  
[년도]    [홍      ]  [이      ]
 
위같은 형태로 바꾸었습니다. 이쿼리는 원래 DB에서 하시는게 더 쉽게 만들수 있고요.
 
보시다싶이 씨리즈에 Y 멤버로 Cnt1, Cnt2로 각각 부여하면 챠트는 알아서 그려줍니다.
 
나머지 꾸미는 건 찾아보시면서 하시면 되겠네요 ^^;
 
아참 챠트가 Bar(Column) 형태인데요. 이건 챠트 타입을 바꿔주시면 됩니다.
 
수고하세요.
 

== 이하 소스입니다. ==
 
public Form1()
        {
            InitializeComponent();
            DataTable dt = new DataTable();
            dt.Columns.Add("YM");
            dt.Columns.Add("ID");
            dt.Columns.Add("CNT", typeof( double ));
            dt.Rows.Add("2010-10", "홍", 4d);
            dt.Rows.Add("2010-10", "홍", 3d);
            dt.Rows.Add("2010-10", "이", 1d);
            dt.Rows.Add("2010-09", "홍", 2d);
            dt.Rows.Add("2010-09", "이", 5d);
            var tmp2 = from k in dt.AsEnumerable()
                       group k by k.Field<string>("YM") into t
                       select new
                       {
                           Key = t.Key,
                           CNT1 = (from h in t
                                  where h.Field<string>("ID") == "홍"
                                  select Convert.ToDouble(h.Field<object>("CNT"))).Sum(),
                           CNT2 = (from h in t
                                   where h.Field<string>("ID") == "이"
                                   select Convert.ToDouble(h.Field<object>("CNT"))).Sum()
                       };

            DataTable source = new DataTable();
            source.Columns.Add("YM");
            source.Columns.Add("CNT1");
            source.Columns.Add("CNT2");
            foreach (var item in tmp2)
            {
                source.Rows.Add(item.Key, item.CNT1, item.CNT2);
            }
            chart1.Series.Clear();
 
            var tt = dt.AsEnumerable().Select(title => title.Field<string>("ID")).Distinct<string>();
            foreach (var item in tt)
            {
                chart1.Series.Add(item);
            }
            chart1.DataSource = source;
            chart1.ChartAreas[0].AxisX.Title = "년도";
            int cnt = 1;
            foreach (var item in chart1.Series)
            {
                item.AxisLabel = "접속 카운트";
                item.XValueMember = "YM";
                item.YValueMembers = "CNT" + cnt.ToString();
                cnt++;
            }           
        }