상권's

TIL 36 (sql 과제 풀기, morgan)(2021.11.15) 본문

~2022 작성 글/TIL

TIL 36 (sql 과제 풀기, morgan)(2021.11.15)

라마치 2021. 11. 15. 16:20
-오늘의 코플릿 2021.11.15-
정수를 요소로 갖는 배열을 입력받아 다음의 조건을 만족하는 LSCS*를 리턴해야 합니다.
LSCS: 주어진 배열의 연속된 부분 배열*의 합을 구한다고 할 때, 이 중 가장 큰 값(Largest Sum of Contiguous Subarray)
연속된 부분 배열들: 배열 [1,2,3]의 연속 부분 배열은 [1], [1, 2], [1, 2, 3], [2], [2, 3], [3] 입니다.
주의사항
배열의 모든 요소가 음수인 경우도 있습니다.
가장 기본적인 방법은 멱집합을 통해서 배열을 다 만든 다음에, 해당 배열들의 모든 요소들을 더하고, 
가장 큰 값을 리턴한다.

첫 수도코드 => 처음 문제를 봤을 때, 연속 된 부분 배열에 대한 예시가 멱집합을 구현해 놓은 거랑 똑같아 보여서, '아 그러면 멱집합 구해서 다 더한 것 중에 큰 값을 리턴하면 되겠네'라는 생각을 했습니다. 근데 그렇게 구현해놓고 테스트 통과가 안되서 다시 한 번 더 문제를 읽어보니 '연속된 부분 배열'이었습니다. 그래도 멱집합 구현이나 해당 코드 구현이 크게 어렵지는 않아서 금방 코드로 구현하고 문제를 해결할 수 있었습니다.

 

배열에 음수들만 들어왔을 경우가 있어서, 일단은 max를 배열의 첫번째 값으로 넣어주고, 아래와 같이 코드를 구현해보았습니다.

const LSCS = function (arr) {
  let result = 0;
  let max = arr[0];
  for ( let n = 0; n < arr.length; n++ ) {
    result += arr[n]
    if (result > max) {
      max = result
    }
    if (result < 0) {
      result = 0;
    }
  }
  return max
};

Difference between Left Join and Right Join 출처 

 

이번 과정 중에서 sql 을 사용하는 문제가 있었는데, join 에 대해서 헷갈리는 부분이 있어서 right join과 left join에 대해서 조금 더 자세하게 알아보겠습니다.

 

MySQL has mainly two kinds of joins named LEFT JOIN and RIGHT JOIN. The main difference between these joins is the inclusion of non-matched rows.

LEFT JOIN과 RIGHT JOIN의 주요 차이점은 매칭이 되지 않는 열의 포함 여부 입니다.

 

The LEFT JOIN includes all records from the left side and matched rows from the right table, whereas RIGHT JOIN returns all rows from the right side and unmatched rows from the left table.

LEFT JOIN은 LEFT SIDE의 모든 Record를 포함하고, 여기에 RIGHT TABLE의 매칭되는 열을 나타냅니다.

RIGHT JOIN은 RIGHT SIDE의 모든 Record를 포함하고, 여기에 LEFT TABLE의 매칭되는 열을 나타냅니다.

 

LEFT JOIN

SELECT columns    
FROM table1    
LEFT [OUTER] JOIN table2    
ON Join_Condition;

In the above syntax, table1 is the left-hand table, and table2 is the right-hand table. This clause returns all records from table1 and matched records from table2 based on the specified join condition.

 

RIGHT JOIN

SELECT column_list  
FROM Table1  
RIGHT [OUTER] JOIN Table2   
ON join_condition;

This Join starts selecting the columns from the right-hand table and matches each record of this table form the left table. If both records fulfill the given join condition, it combines all columns in a new row set that will be returned as output. If the rows of the right-side table do not find any matching rows form the left table, it combines those rows from the right-side table with Null values.

 

LEFT TABLE에서 매칭되는 정보를 찾지 못할 경우에 오른쪽 테이블의 행을 NULL값과 결합합니다.

 

It means, the Right Join returns all data from the right-side table weather it matches the rows form the left table or not.

 

LEFT JOIN & RIGHT JOIN

It joins two or more tables, returns all records from the left table, and matching rows from the right-hand table. It is used to join two or more tables, returns all records from the right table, and matching rows from the left-hand table.
The result-set will contain null value if there is no matching row on the right side table. The result-set will contain null value if there is no matching row on the left side table.
It is also known as LEFT OUTER JOIN. It is also called as RIGHT OUTER JOIN.

id / name / email

1 duhyunkim duhyun.kim@codestates.com
2 seunghwanoh seunghwan.oh@codestates.com
3 junhongpark junhong.park@codestates.com
4 jinsukjeong jinsuk.jeong@codestates.com

[표] user 테이블 데이터

 

id / title / body / created_at / userId

1 database sprint database is easy now 1
2 deploy sprint deploydeploy now null
3 first project happyhacking now null

[표] content 테이블 데이터

 

위와 같은 테이블들이 있고,

'content의 title과 그 컨텐츠를 작성한 user의 name을 찾기 위한 SQL을 작성해주세요.'

이 문제에 대해 제가 작성했던 sql 문입니다.

 

RIGHT JOIN의 경우,  USER 테이블에 ON 이후의 컨디션에 맞게 CONTENT 테이블을 매칭을 시킵니다. 그래서 쓴 책이 있는 김두현에게만 책의 제목이 출력이 되었고, 나머지는 쓴 책이 없어서 NULL 값이 출력됩니다.

 SELECT content.title, user.name FROM content RIGHT JOIN user ON content.userId = user.id

THIS IS RESULT : 
┌─────────┬───────────────────┬───────────────┐
│ (index) │       title       │     name      │
├─────────┼───────────────────┼───────────────┤
│    0    │ 'database sprint' │  'duhyunkim'  │
│    1    │       null        │ 'seunghwanoh' │
│    2    │       null        │ 'junhongpark' │
│    3    │       null        │ 'jinsukjeong' │
│    4    │       null        │  'sangkwon'   │
└─────────┴───────────────────┴───────────────┘

반면,  LEFT JOIN의 경우,  CONTENT 테이블에 ON 이후의 컨디션에 맞게 USER 테이블을 매칭을 시킵니다. 그래서 CONTENT에 있는 모든 책들과 그 책을 쓴 작가가 출력되어야 하는데, 나머지는 작가가 미상으여서 NULL 값으로 출력 됩니다.

 SELECT content.title, user.name FROM content LEFT JOIN user ON content.userId = user.id

THIS IS RESULT : 
┌─────────┬───────────────────┬─────────────┐
│ (index) │       title       │    name     │
├─────────┼───────────────────┼─────────────┤
│    0    │ 'database sprint' │ 'duhyunkim' │
│    1    │  'deploy sprint'  │    null     │
│    2    │  'first project'  │    null     │
└─────────┴───────────────────┴─────────────┘

    TODO: Q 5-2-2. user의 name과 email 그리고 그 user가 속한 role name(컬럼명: roleName)을 찾기 위한 SQL을 작성해주세요.
        - 속한 role이 없더라도, user의 name과 email,role name을 모두 찾아야합니다.
*/
const PART5_2_2 = `SELECT user.name, user.email, role.name AS roleName 
FROM user LEFT JOIN role 
ON user.roleId = role.id`;

USER의 ROLE NAME 을 매칭할 때 원하는 컬럼명을 지정할 수 있는 방법입니다. => AS


    TODO: Q 5-2-8. category의 name이 soccer인 content의 title, body, created_at, user의 name을 찾기위한 SQL을 작성해주세요.
*/
const PART5_2_8 = `SELECT content.title, content.body, content.created_at, user.name FROM content 
                JOIN user ON content.userId = user.id
                JOIN content_category ON content.id = content_category.contentId
                JOIN category ON content_category.categoryId = category.id WHERE category.name = 'soccer'`;

복수의 JOIN을 통해서 원하는 정보를 찾는 sql 문을 구현해보았습니다.


----------------------------------------------------------------------------------------------
    TODO: Q 5-2-9. duRiCha가 작성한 글의 개수 (컬럼명: ContentCount)를 출력하기 위한 SQL을 작성해주세요.
*/
const PART5_2_9 = `SELECT COUNT(title) AS ContentCount FROM content JOIN user 
ON content.userId = user.id WHERE user.name = 'duRiCha'`;

/*
----------------------------------------------------------------------------------------------
    TODO: Q 5-2-10. 각 user(컬럼명: name)가 작성한 글의 개수 (컬럼명: ContentCount)를 출력하기 위한 SQL을 작성해주세요.
*/
const PART5_2_10 = `SELECT COUNT(title) ContentCount, user.name name 
FROM content RIGHT JOIN user ON content.userId = user.id GROUP BY user.name`;

작가별로 작성한 글의 갯수(COUNT)를 확인하기 위한 sql 문을 구현해보았습니다. AS의 경우, 띄어쓰기로 생략할 수도 있습니다.

 


데이터베이스 정규화 (Database Normalization)

데이터 중복(data redundancy)은 실제 데이터의 동일한 복사본이나, 부분적인 복사본을 뜻합니다. 물론 이러한 중복으로 데이터를 복구할 때에 더 수월할 수도 있습니다. 그러나 대체로 데이터베이스 내에서는 몇 가지 문제점을 지닙니다.

  • 일관된 자료 처리의 어려움
  • 저장 공간 낭비
  • 데이터 효율성 감소

 

Data Integrity

데이터 정규화는 데이터 무결성을 강화하는 목적도 지닙니다.

데이터 무결성(data integrity)은 데이터의 수명 주기 동안 정확성과 일관성을 유지하는 것을 뜻합니다.
다시 말해 입력된 데이터가 오염되지 않고, 입력된 그대로 데이터를 사용할 수 있다는 뜻입니다.

 

Anomaly

데이터 이상 현상(anomaly)은 기대한 데이터와 다른, 이상 현상을 가리킵니다.

다음과 같은 3가지 현상이 있습니다:

  • 갱신 이상(update anomaly)
  • 삽입 이상(insertion anomaly)
  • 삭제 이상(deletion anomaly)

 

- Update Anomaly

갱신 이상(update anomaly)은 여러 행(레코드)에 걸쳐 동일한 데이터가 있을 때, 어떤 행을 갱신해야 하는지 논리적인 일관성이 없는 경우에 발생합니다.

- Insertion Anomaly

삽입 이상(insertion anomaly)은 데이터를 삽입하지 못하는 경우를 가리킵니다.

 

- Deletion Anomaly

삭제 이상(deletion anomaly)은 데이터의 특정 부분을 지울 때 의도치 않게 다른 부분도 함께 지우는, 이상 현상입니다.


SQL 종류

SQL에는 데이터를 조회하고 테이블을 만드는 등 다양한 문법이 있습니다. 그리고 쿼리문을 어떻게 작성하느냐에 따라, 그 기능이나 작업이 달라집니다. 영어나 한국어 등과 같은 언어에서 주어나 동사 등을 구분하는 것처럼 SQL에서도 역할에 따라 문법이 다양하게 존재합니다.

 

Data Definition Language(DDL) 데이터 정의어 

DDL(Data Definition Language)은 데이터를 정의할 때 사용하는 언어입니다. 테이블을 만들 때 사용하는 CREATE나 테이블을 제거할 때 사용되는 DROP 등이 DDL에 해당합니다. 데이터베이스의 테이블과 같은 오브젝트를 정의할 때 사용합니다.

create, alter, drop, truncate

 

Data Manipulation Language(DML) 데이터 조작어

DML(Data Manipulation Language)은 데이터베이스에 데이터를 저장할 때 사용하는 언어입니다. INSERT처럼 새로운 레코드를 추가할 때 사용되는 문법을 포함해 데이터를 삭제하는 DELETE 나, 변경하는 UPDATE가 DML에 포함됩니다.

update, delete, insert, select

 

Data Control Language(DCL) 데이터 관리어

DCL(Data Control Language)은 데이터베이스에 대한 접근 권한과 관련된 문법입니다. 어느 유저가 데이터베이스에 접근할 수 있는지 권한을 설정합니다. 권한을 주는 GRANT 나, 권한을 가져가는 REVOKE 등이 DCL에 포함됩니다.

grant, revoke

 

Data Query Language(DQL)

DQL(Data Query Language)은 정해진 스키마 내에서 쿼리할 수 있는 언어입니다. SELECT 가 DQL에 해당합니다. 이렇게 언어를 분류했지만, DQL을 DML의 일부분으로 취급하기도 합니다.

 

Transaction Control Language(TCL)

TCL(Transaction Control Language)은 DML을 거친 데이터의 변경사항을 수정할 수 있습니다. COMMIT 처럼 DML이 작업한 내용을 데이터베이스에 커밋하거나, ROLLBACK 처럼 커밋했던 내용을 다시 롤백하는 문법이 있습니다.

commit, rollback


CASE 사용하기

CASE 를 사용하면, 특정 조건에 따라 다른 결과를 받을 수 있습니다.

SELECT CASE
WHEN CustomerId <= 25 THEN 'GROUP 1'
WHEN CustomerId <= 50 THEN 'GROUP 2'
ELSE 'GROUP 3'
	END
FROM customers

이 쿼리문은 CustomerId 필드값에 따라 3개의 그룹('GROUP 1', 'GROUP 2', 'GROUP 3')으로 나뉩니다. CustomerId 필드값이 25 이하인 경우에는 'GROUP 1', 26부터 50 사이인 경우에는 'GROUP 2', 51 이상은 'GROUP 3' 으로 분류합니다.

 

SUBQUERY

쿼리문을 작성할 때, SUBQUERY(서브쿼리)를 포함할 수 있습니다. 서브쿼리는 실행되는 쿼리에 중첩으로 위치해, 정보를 전달합니다. 서브쿼리는 소괄호로 감싸야 합니다.

 

서브쿼리의 결과는 개별 값이나 레코드 리스트입니다. 그리고 서브쿼리의 결과를 하나의 칼럼으로 사용할 수 있습니다.

SELECT CustomerId, CustomerId = (SELECT CustomerId FROM customers WHERE CustomerId = 2)
FROM customers
WHERE CustomerId < 6

 

IN, NOT IN

IN은 특정한 값이 서브쿼리에 있는지 확인할 수 있습니다. 다음 쿼리는 customers 테이블에서 'CustomerId' 의 값이 서브쿼리에서 돌려받는 값에 속한 결과들만 조회하고 있습니다.

SELECT *
FROM customers
WHERE CustomerId IN (SELECT CustomerId FROM customers WHERE CustomerId < 10)

서브쿼리에서는 'CustomerId' 가 10 이하인 데이터를 돌려주기 때문에, 최종 조회된 데이터의 'CustomerId'도 10 이하입니다.

 

만약 IN 대신 NOT IN 을 사용한다면, 서브쿼리에서 조회된 10 미만을 제외한(10을 초과하는) 레코드를 조회합니다.

 

EXISTS

EXISTS 또는 NOT EXISTS는 돌려받은 서브쿼리에 존재하는 레코드를 확인합니다.
만약 조회하려는 레코드가 존재한다면 참(TRUE)을, 그렇지 않은 경우에는 거짓(FALSE)을 리턴합니다.


다음 쿼리문은 employees 테이블에서부터 'EmployeeId' 필드를 조회합니다. 이때 서브쿼리로 customers 테이블의 'SupportRepId' 필드값과 employees 테이블의 'EmployeeId' 필드값을 비교해 일치하는 레코드들을 가져옵니다.

SELECT EmployeeId
FROM employees e
WHERE EXISTS (
	SELECT 1
	FROM customers c
	WHERE c.SupportRepId = e.EmployeeId
	)
ORDER BY EmployeeId

 

FROM

FROM에도 서브쿼리를 사용할 수 있습니다.
다음과 같이 쿼리문과 서브쿼리를 사용해 조회된 결과를 하나의 테이블이나 조회할 대상으로 지정해 사용할 수 있습니다.

SELECT *
FROM (
	SELECT CustomerId
	FROM customers
	WHERE CustomerId < 10
	)

 


sql cheat sheet 


morgan

오늘 일과 후에 추가적인 학습을 하던 중 알게 된 미들웨어 입니다.

HTTP request logger middleware for node.js

 

HTTP request 요청에 대한 정보를 콘솔에 찍어주는 미들웨어입니다.

 

이를 통해서 로그 관리를 손 쉽게 할 수 있습니다.

 

아직은 이론에 대해서만 간단하게 배웠지만, 추후 사용하면서 상황에 따른 로그 내용을 학습해서 블로그에 올려보겠습니다.


curl 은 command line 용 data transfer tool 이다. download/upload 모두 가능하며 

HTTP/HTTPS/FTP/LDAP/SCP/TELNET/SMTP/POP3 등 주요한 프로토콜을 지원하며 Linux/Unix 계열 및 Windows 등 주요한 OS 에서 구동되므로 여러 플랫폼과 OS에서 유용하게 사용할 수 있다. 

 

주요 옵션

curl [options...] <url> 형식으로 사용하면 된다.

option 처리는 GNU getopt 를 사용하므로 하이픈 하나를 붙이는 short 형식의 옵션과 하이픈 두개로 시작되는 long 형식의 options 이 있다. 

 

출처

 

주요 options (http/https 관련 옵션만 정리)

-k --insecure https 사이트를 SSL certificate
검증없이 연결한다.
wget 의 --no-check-certificate 과
비슷한 역할 수행
-l --head HTTP header 만 보여주고 content 는
표시하지 않는다
 
-D --dump-header <file> <file> 에 HTTP header 를 기록한다.  
-L --location 서버에서 HTTP 301이나  HTTP 302 응답이 왔을 경우 redirection URL 로 따라간다.
--max-redirs 뒤에 숫자로 redirection 을 몇 번
따라갈지 지정할 수 있다. 기본 값은 50이다
curl -v daum.net 을
실행하면 결과값으로 다음과
같이 HTTP 302 가 리턴된다.

< HTTP/1.1 302 Object Moved
< Location: http://www.daum.net/
-L 옵션을 추가하면 www.daum.net 
으로 재접속하여 결과를 받아오게 된다.
-d --data HTTP Post data FORM 을 POST 하는 HTTP나
JSON 으로 데이타를 주고받는
REST 기반의 웹서비스 디버깅시
유용한 옵션이다
-v --verbose  동작하면서 자세한 옵션을 출력한다.  
-J --remote-header-name 어떤 웹서비스는 파일 다운로드시 
Content-Disposition Header 를 파싱해야 정확한 파일이름을 알 수 있을 경우가 있다.
-J 옵션을 주면 헤더에 있는
파일 이름으로 저장한다.
curl 7.20 이상부터 추가된 옵션
-o --output FILE curl 은 remote 에서 받아온 데이타를
기본적으로는 콘솔에 출력한다.
-o 옵션 뒤에 FILE 을 적어주면
해당 FILE 로 저장한다. (download 시 유용)
 
-O --remote-name file 저장시 remote 의 file 이름으로 저장한다.
-o 옵션보다 편리하다.
 
-s --silent 정숙 모드. 진행 내역이나 메시지등을
출력하지 않는다.
-o 옵션으로 remote data 도 /dev/null 로
보내면 결과물도 출력되지 않는다
HTTP response code 만
가져오거나 할 경우 유리
-X --request Request 시 사용할 method 종류(GET, POST,
PUT, PATCH, DELETE) 를 기술한다.
 

 

Comments