보너스: A great paper with a wonderful illustration how we approach system design, even in agile software development. Start with synthesis, build an hypothesis, then analysis. Then iterate and iterate. via @trondhjort
인프런에 면접을 부르는 '개발자 이력서' 쓰기라는 강의를 올렸고 출시하자마자 바로 인프런의 첫 페이지에서도 가장 좋은 위치에 올라왔다. 특히 개발자 이력서를 쓰시는 분들의 고충을 덜어드리기 위해 어떻게 하면 면접관의 관심을 끌 수 있을지에 대해 이력서를 강화하는 힌트와 팁을 드리므로 매번 이력서 작성하시느라 밤잠을 설치신 분들께 조금이라도 도움이 되지 않을까 하는 생각이다.
출시 기념으로 세 분에게 무료 수강을 할 수 있는 쿠폰을 나눠드리는 이벤트를 유튜브에서 진행하고 있으므로 많은 성원 부탁드리겠다.
당첨자(이하생, Shin Hang Ja, Richard Cha, Ravn Thomas, HS Song) 여러분들께서는 jrogue 에뜨 gmail.com으로 주소, 성명, 전화번호를 보내주시면 내주 초에 선물(!)을 우편으로 발송할 계획이다
그리고 보너스 소식 하나: 3월 16일(화), 3월 23일(화), 3월 30일(화) 3회에 걸쳐 22시 정각부터 45분 정도 유튜브 라이브로 블록체인 기업으로 가는 길 책 같이 읽는 시리즈를 진행할 예정이다. 3월 9일(화) 밤 10시에 유튜브 라이브로 간단하게 진행 방법을 소개드릴 예정이오니 많은 성원을 부탁드리겠다.
집계 함수는 계산 결과를 한 행으로 합치는 특성이 있는 반면에 윈도우 함수는 원래 행을 그대로 유지하는 특성이 있다
값과 순위를 매기는 함수가 대표적이다.
단계 2: (값) LAST VALUE(정해진 윈도우 프레임 내에서 마지막 행의 값을 반환)
SQL> SELECT Name, printf ( '%.f minutes', Milliseconds / 1000 / 60 ) AS Length, LAST_VALUE ( Name ) OVER ( ORDER BY Milliseconds RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS LongestTrack FROM tracks WHERE AlbumId = 4;
SQL> SELECT AlbumId, Name, printf ( '%.f minutes', Milliseconds / 1000 / 60 ) AS Length, LAST_VALUE ( Name ) OVER ( PARTITION BY AlbumId ORDER BY Milliseconds DESC RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS ShortestTrack FROM tracks;
단계 3: LEAD(직후에 물리적으로 떨어진 오프셋 값을 가져오기)
SQL> CREATE VIEW CustomerInvoices AS SELECT CustomerId, strftime('%Y',InvoiceDate) Year, SUM( total ) Total FROM invoices GROUP BY CustomerId, strftime('%Y',InvoiceDate);
SQL> SELECT * FROM CustomerInvoices ORDER BY CustomerId, Year, Total;
SQL> SELECT CustomerId, Year, Total, LEAD ( Total,1,0 ) OVER ( ORDER BY Year ) NextYearTotal FROM CustomerInvoices WHERE CustomerId = 1;
SQL> SELECT CustomerId, Year, Total, LEAD ( Total,1,0 ) OVER ( PARTITION BY CustomerId ORDER BY Year ) NextYearTotal FROM CustomerInvoices;
단계 4: (값) NTH_VALUE(정해진 윈도우 프레임 내에서 N번째 행의 값을 반환)
SQL> SELECT Name, Milliseconds Length, NTH_VALUE ( name,2 ) OVER ( ORDER BY Milliseconds DESC ) SecondLongestTrack FROM tracks;
SQL> SELECT AlbumId, Name, Milliseconds Length, NTH_VALUE ( Name,2 ) OVER ( PARTITION BY AlbumId ORDER BY Milliseconds DESC RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS SecondLongestTrack FROM tracks;
단계 5: (순위) NTILE(순서가 있는 결과 집합을 정해진 버킷에 나눠서 넣기)
SQL> SELECT Name, Milliseconds, NTILE ( 4 ) OVER ( ORDER BY Milliseconds ) LengthBucket FROM tracks WHERE AlbumId = 1;
SQL> SELECT AlbumId, Name, Milliseconds, NTILE ( 3 ) OVER ( PARTITION BY AlbumId ORDER BY Bytes ) SizeBucket FROM tracks;
단계 6: (순위) PERCENT_RANK(순위를 퍼센트로 보여줌)
SQL> SELECT Name, Milliseconds, PERCENT_RANK() OVER( ORDER BY Milliseconds ) LengthPercentRank FROM tracks WHERE AlbumId = 1;
SQL> SELECT Name, Milliseconds, printf('%.2f',PERCENT_RANK() OVER( ORDER BY Milliseconds )) LengthPercentRank FROM tracks WHERE AlbumId = 1;
SQL> SELECT AlbumId, Name, Bytes, printf('%.2f',PERCENT_RANK() OVER( PARTITION BY AlbumId ORDER BY Bytes )) SizePercentRank FROM tracks;
단계 7: (순위) RANK(순위를 보여줌, 중복 가능, 빈 순서 있음)
SQL> CREATE TABLE RankDemo ( Val TEXT );
SQL> INSERT INTO RankDemo(Val) VALUES('A'),('B'),('C'),('C'),('D'),('D'),('E');
SQL> SELECT * FROM RankDemo;
SQL> SELECT Val, RANK () OVER ( ORDER BY Val ) ValRank FROM RankDemo;
SQL> SELECT Name, Milliseconds, RANK () OVER ( ORDER BY Milliseconds DESC ) LengthRank FROM tracks;
SQL> SELECT Name, Milliseconds, AlbumId, RANK () OVER ( PARTITION BY AlbumId ORDER BY Milliseconds DESC ) LengthRank FROM tracks;
SQL> SELECT * FROM ( SELECT Name, Milliseconds, AlbumId, RANK () OVER ( PARTITION BY AlbumId ORDER BY Milliseconds DESC ) LengthRank FROM tracks ) WHERE LengthRank = 2;
SQL>
단계 8: (순위) ROW_NUMBER(연속적인 정수를 부여, 중복 불가능)
SQL> SELECT ROW_NUMBER () OVER ( ORDER BY Country ) RowNum, FirstName, LastName, country FROM customers;
SQL> SELECT ROW_NUMBER () OVER ( PARTITION BY Country ORDER BY FirstName ) RowNum, FirstName, LastName, country FROM customers;
SQL> SELECT * FROM ( SELECT ROW_NUMBER () OVER ( ORDER BY FirstName ) RowNum, FirstName, LastName, Country FROM customers ) WHERE RowNum > 20 AND RowNum <= 30
SQL> CREATE VIEW Sales AS SELECT CustomerId, FirstName, LastName, Country, SUM( total ) Amount FROM invoices INNER JOIN customers USING (CustomerId) GROUP BY CustomerId;
SQL> SELECT Country, FirstName, LastName, Amount FROM ( SELECT Country, FirstName, LastName, Amount, ROW_NUMBER() OVER ( PARTITION BY country ORDER BY Amount DESC ) RowNum FROM Sales ) WHERE RowNum = 1;