<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>sss_yeonii.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sun, 24 Nov 2024 09:48:26 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>sss_yeonii.log</title>
            <url>https://velog.velcdn.com/images/sss_yeonii/profile/577eb708-7c4b-4232-86c8-b611e822c0bb/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. sss_yeonii.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/sss_yeonii" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[모델 평가 지표]]></title>
            <link>https://velog.io/@sss_yeonii/%EB%AA%A8%EB%8D%B8-%ED%8F%89%EA%B0%80-%EC%A7%80%ED%91%9C</link>
            <guid>https://velog.io/@sss_yeonii/%EB%AA%A8%EB%8D%B8-%ED%8F%89%EA%B0%80-%EC%A7%80%ED%91%9C</guid>
            <pubDate>Sun, 24 Nov 2024 09:48:26 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/44e2b6f3-c1e1-4b36-9b2c-bb165c7017e0/image.png" alt=""></p>
<ul>
<li>Sensitivity = Recall = 재현율
<img src="https://velog.velcdn.com/images/sss_yeonii/post/9aa982cc-ecd9-43a1-a02b-464c863304a4/image.png" alt="">
<img src="https://velog.velcdn.com/images/sss_yeonii/post/cc5e495d-51f1-40fe-88ec-ae94a3f983d5/image.png" alt=""></li>
<li>제 1종 오류 보다 제 2종 오류가 더 심각할 수 있음</li>
<li>제 2종 오류: Recall - 실제 Positive인데 Negative라고 판단한 것
<img src="https://velog.velcdn.com/images/sss_yeonii/post/e1dccc5b-ad83-4dfc-8ab9-559ef7b094f1/image.png" alt="">
<img src="https://velog.velcdn.com/images/sss_yeonii/post/2de4aa7d-a20a-43de-a5b4-6edcb10c0fdf/image.png" alt="">
<img src="https://velog.velcdn.com/images/sss_yeonii/post/b2acc186-2fb4-4930-98c9-a9b2bc39b541/image.png" alt="">
<img src="https://velog.velcdn.com/images/sss_yeonii/post/f4af2ff9-4f06-49b1-bb20-660658f917ff/image.png" alt=""></li>
<li>실제 Positive인 데이터를 Negative라고 잘못 판단하면 안되는 경우 =&gt; Recall이 더 중요 (e.g. 임신: 임신인데 임신이 아니라고 처리한 경우)</li>
<li>실제 Negative인 데이터를 Positive라고 잘못 판단하면 안되는 경우 =&gt; Precision이 더 중요 (e.g. 스팸: 중요한 메일인데 스팸(1)으로 처리한 경우)</li>
<li>그러나, Recall과 Precision은 서로 영향을 주기 때문에 한쪽을 극단적으로 높게 설정하면 안됨
<img src="https://velog.velcdn.com/images/sss_yeonii/post/dbe0c935-0823-4dc0-ac1d-915901541e0a/image.png" alt=""></li>
<li>Recall과 Precision 둘다 높을 수록 F1 스코어는 높은 값을 가지고, 더 좋은 모델이라는 뜻임</li>
<li>B(베타)가 1일 때가 F1 Score라고 부름
<img src="https://velog.velcdn.com/images/sss_yeonii/post/8d9aee06-0ab2-4997-8035-e5292b87860d/image.png" alt=""></li>
<li>FPR(Fall-out, 실제 Negative 중에 Positive로 예측한 것), TPR(Recall, 실제 Positive 중에 Positive인 것)</li>
</ul>
<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/191e4c6b-e089-4036-aa5e-5877ea262a2c/image.png" alt="">
<img src="https://velog.velcdn.com/images/sss_yeonii/post/6adcfeb6-e859-4444-ab51-175a53f75ade/image.png" alt="">
<img src="https://velog.velcdn.com/images/sss_yeonii/post/8de6d391-a14c-482a-be1c-cc5f1d88f03c/image.png" alt="">
<img src="https://velog.velcdn.com/images/sss_yeonii/post/c738c5b7-e22a-49e5-9318-21097d5b029f/image.png" alt="">
<img src="https://velog.velcdn.com/images/sss_yeonii/post/9f07c64e-ebb7-4ae5-8b21-42ac6b78847e/image.png" alt=""></p>
<ul>
<li>Recall(TPR)과 Fall-out(FPR) 수치로 그래프를 그려봤을 때, 1X1 면적을 거의 다 채울수록 좋은 수치</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Github Markdown 문법(Readme 활용)]]></title>
            <link>https://velog.io/@sss_yeonii/Github-Markdown-%EB%AC%B8%EB%B2%95Readme-%ED%99%9C%EC%9A%A9</link>
            <guid>https://velog.io/@sss_yeonii/Github-Markdown-%EB%AC%B8%EB%B2%95Readme-%ED%99%9C%EC%9A%A9</guid>
            <pubDate>Sun, 08 Sep 2024 07:32:10 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>README에서 사용하는 Markdown을 소개합니다.</p>
</blockquote>
<h1 id="-제목-">[ 제목 ]</h1>
<p><strong>&lt; Input &gt;</strong></p>
<pre><code>This is H1
====

This is H2
----</code></pre><p>혹은</p>
<pre><code># This is H1
## This is H2
### This is H3
#### This is H4
##### This is H5
###### This is H6</code></pre><p><strong>&lt; Output &gt;</strong></p>
<h1 id="this-is-h1">This is H1</h1>
<h2 id="this-is-h2">This is H2</h2>
<h3 id="this-is-h3">This is H3</h3>
<h4 id="this-is-h4">This is H4</h4>
<h5 id="this-is-h5">This is H5</h5>
<h6 id="this-is-h6">This is H6</h6>
<h1 id="-blockquote-">[ Blockquote ]</h1>
<blockquote>
<p>This is a first blockquote.</p>
<blockquote>
<p>This is a second blockquote.</p>
<blockquote>
<p>This is a third blockquote.</p>
</blockquote>
</blockquote>
</blockquote>
<pre><code>&gt; This is a first blockquote.
&gt;&gt; This is a second blockquote.
&gt;&gt;&gt; This is a third blockquote.</code></pre><h1 id="-혼합해서-사용하기-">[ 혼합해서 사용하기 ]</h1>
<blockquote>
<h3 id="this-is-h3-1">This is H3</h3>
<ul>
<li>List</li>
</ul>
</blockquote>
<pre><code>&gt; ### This is H3
&gt; * List</code></pre><h1 id="-순서가-있는-목록-">[ 순서가 있는 목록 ]</h1>
<ol>
<li>첫번째</li>
<li>두번째</li>
<li>세번째</li>
</ol>
<pre><code>1. 첫번째
2. 두번째
3. 세번째</code></pre><h1 id="-순서가-없는-목록-">[ 순서가 없는 목록 ]</h1>
<ul>
<li>별표<ul>
<li>별표<ul>
<li>별표</li>
</ul>
</li>
</ul>
</li>
<li>더하기<ul>
<li>더하기<ul>
<li>더하기</li>
</ul>
</li>
</ul>
</li>
<li>빼기<ul>
<li>빼기<ul>
<li>빼기</li>
</ul>
</li>
</ul>
</li>
</ul>
<pre><code>* 별표
  * 별표
    * 별표
+ 더하기
  + 더하기
    + 더하기
- 빼기
  - 빼기
    - 빼기</code></pre><h1 id="-코드-블럭-">[ 코드 블럭 ]</h1>
<pre><code>
  코드 내용 입력</code></pre>

<p><code> pre 없이 코드 내용 입력할 경우 </code></p>
<pre><code>코드 내용 입력</code></pre><p><code>print(&#39;하나만 사용함&#39;)</code></p>
<p><strong>&lt; Input &gt;</strong></p>
<pre><code>&lt;pre&gt;&lt;code&gt;
  코드 내용 입력&lt;/code&gt;&lt;/pre&gt;

&lt;code&gt; pre 없이 코드 내용 입력할 경우 &lt;/code&gt;

/```
코드 내용 입력
/```

`print(&#39;하나만 사용함&#39;)`</code></pre><h1 id="-수평선-">[ 수평선 ]</h1>
<hr>
<hr>
<hr>
<hr>
<hr>
<pre><code>* * *
***
*****
- - - 
--------</code></pre><h1 id="-외부-링크-">[ 외부 링크 ]</h1>
<p>Link: <a href="https://www.naver.com/," title="naver link">NAVER</a>
외부링크: <a href="https://www.naver.com/">https://www.naver.com/</a>
이메일링크: <a href="mailto:&#105;&#x64;&#x40;&#x67;&#x6d;&#97;&#105;&#108;&#46;&#99;&#111;&#x6d;">&#105;&#x64;&#x40;&#x67;&#x6d;&#97;&#105;&#108;&#46;&#99;&#111;&#x6d;</a></p>
<pre><code>Link: [NAVER](https://www.naver.com/, &quot;naver link&quot;)
외부링크: &lt;https://www.naver.com/&gt;
이메일링크: &lt;id@gmail.com&gt;</code></pre><h1 id="-강조-">[ 강조 ]</h1>
<p>이탤릭체</p>
<ul>
<li><em>single asterisks</em> </li>
<li><em>single underscores</em></li>
</ul>
<p>굵게</p>
<ul>
<li><strong>double asterisks</strong></li>
<li><strong>double underscores</strong></li>
</ul>
<p>취소선</p>
<ul>
<li><del>cancleline</del></li>
</ul>
<h1 id="-이미지-">[ 이미지 ]</h1>
<p>이미지가 어딘가 업로드되어 있어야 하기 때문에 github Issue를 활용한다.</p>
<ol>
<li>Issues로 이동</li>
<li>New Issue</li>
<li>이미지 붙여넣기해서 생성된 링크 그대로 복사 (Issue는 저장하지 않아도 됨)
<img src="https://velog.velcdn.com/images/sss_yeonii/post/1c6ac839-7fa5-48f9-91d2-c5cbeda271f2/image.png" alt=""></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[Github 사용하는 방법 총 정리]]></title>
            <link>https://velog.io/@sss_yeonii/github</link>
            <guid>https://velog.io/@sss_yeonii/github</guid>
            <pubDate>Sun, 08 Sep 2024 07:22:37 GMT</pubDate>
            <description><![CDATA[<h2 id="0-git-config-설정">0. git config 설정</h2>
<p>터미널에서 아래 실행</p>
<pre><code class="language-shell">$ git config --global user.name &lt;username&gt;
$ git config --global user.email &lt;email&gt;
$ git config --global core.autocrlf input

# 설정 완료된 것 확인하기
git config --list
credential.helper=osxkeychain
init.defaultbranch=main
user.name=&lt;username&gt;
user.email=&lt;email&gt;
core.autocrlf=input
core.editor=vim

# 하나씩 쳐서 확인도 가능
$ git config user.name</code></pre>
<h2 id="1-git-기본-용어">1. Git 기본 용어</h2>
<h3 id="repository">Repository</h3>
<ul>
<li>소스코드가 저장되어 있는 여러 개의 Branch가 모여있는 디스크상의 물리적 공간</li>
<li>Local Repository와 Remote Repository로 구분 
=&gt; Repository가 서버에도 있고 로컬에도 있기 때문</li>
</ul>
<h3 id="checkout">Checkout</h3>
<ul>
<li>특정 시점이나 Branch의 소스 코드로 이동하는 것을 의미</li>
<li>Checkout 대상 - Branch, Commit, Tag</li>
<li>Checkout을 통해 과거 여러 시점의 코드로 이동 가능</li>
</ul>
<h3 id="stage">Stage</h3>
<ul>
<li>작업할 내용이 올라가는 임시 저장 영역 </li>
<li>window에 파일 올라가면 working directory에 있는 건데, 여기서 어떤 파일을 선택해서 git에서 관리하겠다고 등록한다면 이제 stage에 올라가게 되는 것. 수정해서 버전을 매기는 행위를 하면 head 영역으로 올라가게 됨.</li>
<li>이 영역을 이용해 작업한 내용 중 commit에 반영할 파일만 선별하여 commit을 수행할 수 있음</li>
</ul>
<h3 id="commit">Commit</h3>
<ul>
<li>작업할 내용을 Local Repository에 저장하는 과정 = 버전을 매기는 행위 </li>
<li>각각의 commit은 의미있는 변경 단위이고, 변경에 대한 설명을 commit log로 남김</li>
<li>권장: commit은 아끼지 마라. 의미있는 단위로 변경할 때마다 commit을 남겨라.</li>
<li>참고: commit 단위나 commit log format을 정해놓은 회사나 팀도 있음(빌드 서버 사용하는 경우)</li>
</ul>
<h3 id="tag">Tag</h3>
<ul>
<li>임의의 commit 위치에 쉽게 찾아갈 수 있도록 붙여놓은 이정표</li>
<li>Tag가 붙은 commit은 commit id(version) 대신 tag name으로 쉽게 checkout 가능 </li>
<li>예를 들어, 3.0 version이 드디어 나왔다면 tag로 3.0을 달아서 2년 뒤에도 쉽게 돌아갈 수 있도록 함.</li>
</ul>
<h3 id="push">Push</h3>
<ul>
<li>Local Repository 내용 중 Remote Repository에 반영되지 않은 commit을 Remote Repository로 보내는 과정</li>
<li>권장: Push하는 순간 Remote로 올라가는 것이라 다른 개발자들도 코드를 가져와서 쓸 수 있음. 이때 실행되지 않는 코드를 올리면 다른 사람의 작업에 방해가 될 수 있기 때문에, 검증되지 않은 코드는 Push하지 않도록 함.</li>
</ul>
<h3 id="pull">Pull</h3>
<ul>
<li>Remote Reposity에 있는 내용 중, Local Repository에 반영되지 않은 내용을 가져와서 Local Repository에 저장하는 과정</li>
<li>다른 팀원이 변경하고 Push한 내용을 Local Repository에 가져올 수 있음</li>
<li>(참고) Push 과정에서 Conflict(충돌)이 일어나서 Push가 거절된 경우, Pull을 통해 Remote Repository의 변경 내용을 Local Repository에 반영하여 Conflict를 해결하나 뒤 다시 Push 시도해야 함</li>
</ul>
<h3 id="branch">Branch</h3>
<ul>
<li>특정 시점(commit 단위)에서 분기하여 새로운 commit을 쌓을 수 있는 가지를 만드는 것</li>
<li>Repository를 처음 생성하면 디폴트로 생성되는 것이 master(혹은 main) branch이며, 이 branch가 개발의 주축이 됨</li>
<li>모든 branch는 최종적으로 다시 master branch에 merge(병합)되는 형식으로 진행됨</li>
</ul>
<h3 id="merge">Merge</h3>
<ul>
<li>Branch의 반대개념으로 하나의 Branch를 다른 Branch와 합치는 과정</li>
<li>Merge되는 두 Branch는 주종관계가 성립. e.g. dev branch를 main branch에 merge</li>
<li>Merge되는 과정에서 Conflict 발생하는 경우 Diff를 수정하여 Conflict 해결한 뒤 Merge 진행할 수 있음</li>
</ul>
<h2 id="2-local-repository-구성">2. Local Repository 구성</h2>
<p> <img src="https://velog.velcdn.com/images/sss_yeonii/post/9e1cfa6b-4532-4522-a40e-5bee18a60727/image.png" alt=""></p>
<ol>
<li>실습할 Workspace 생성 
<code>% mkdir git_ws</code></li>
<li>Working Directory 생성 및 git init하면 해당 폴더를 Local Repository로서 관리</li>
</ol>
<ul>
<li>Workspace로 이동한 뒤 Working Directory 생성</li>
<li><code>git init</code> 폴더에서 Git을 초기화하는 명령어를 사용하면 해당 폴더를 Git이 관리하기 시작<pre><code>% cd git_ws
git_ws % mkdir test_project
git_ws % cd test_project
test_project % git init
Initialized empty Git repository in /Users/sy/git_ws/test_project/.git/</code></pre></li>
</ul>
<ol start="3">
<li>.git 폴더 생성</li>
</ol>
<ul>
<li>.git으로 이동해서 살펴보면 Git 관련 파일들이 생성되어 있음
```
(base) sy@Lees-MacBook-Pro test_project % ls -all
total 0
drwxr-xr-x  3 sy  staff   96  9  7 14:34 .
drwxr-xr-x  4 sy  staff  128  9  7 14:33 ..
drwxr-xr-x  9 sy  staff  288  9  7 14:34 .git
(base) sy@Lees-MacBook-Pro test_project % cd .git
(base) sy@Lees-MacBook-Pro .git % ls -all
total 24
drwxr-xr-x   9 sy  staff  288  9  7 14:34 .
drwxr-xr-x   3 sy  staff   96  9  7 14:34 ..</li>
<li>rw-r--r--   1 sy  staff   21  9  7 14:34 HEAD</li>
<li>rw-r--r--   1 sy  staff  137  9  7 14:34 config</li>
<li>rw-r--r--   1 sy  staff   73  9  7 14:34 description
drwxr-xr-x  15 sy  staff  480  9  7 14:34 hooks
drwxr-xr-x   3 sy  staff   96  9  7 14:34 info
drwxr-xr-x   4 sy  staff  128  9  7 14:34 objects
drwxr-xr-x   4 sy  staff  128  9  7 14:34 refs
```</li>
</ul>
<ol start="4">
<li>Working Directory에 파일을 생성
<code>touch {파일명}</code>: 비어있는 파일 하나를 생성해주는 명령어<pre><code>(base) sy@Lees-MacBook-Pro test_project % touch test.txt
(base) sy@Lees-MacBook-Pro test_project % ls
test.txt</code></pre></li>
<li><code>git status</code> git에 존재하는 파일 확인 -&gt; 자주 확인하는 습관을 들이기 ⭐️<pre><code>(base) sy@Lees-MacBook-Pro test_project % git status
On branch main  # 현재 main branch에 있다
</code></pre></li>
</ol>
<p>No commits yet  # 아직 commit한 건 없다</p>
<p>Untracked files:  # working directory에는 있는데 stage에는 존재하지 않는 파일이 있다
  (use &quot;git add <file>...&quot; to include in what will be committed)
    test.txt</p>
<pre><code>
6. `git add &lt;filename&gt;` ⭐️
- Working Directory에서 변경된 파일을 Stage(Index)에 추가</code></pre><p>(base) sy@Lees-MacBook-Pro test_project % git add test.txt
(base) sy@Lees-MacBook-Pro test_project % git status
On branch main</p>
<p>No commits yet</p>
<p>Changes to be committed:<br>  (use &quot;git rm --cached <file>...&quot; to unstage)
    new file:   test.txt</p>
<pre><code>
7. `git commit -m &quot;commit 변경사항에 대한 설명&quot; &lt;filename&gt;` ⭐️⭐️
- Stage(Index)에 추가된 변경사항을 HEAD에 반영(확정)</code></pre><p>(base) sy@Lees-MacBook-Pro test_project % git commit -m &quot;테스트임&quot; test.txt
[main (root-commit) 4b24e0e] 테스트임
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test.txt
(base) sy@Lees-MacBook-Pro test_project % git status
On branch main
nothing to commit, working tree clean</p>
<pre><code>

*참고) Mac에서 command+shit+. 하면 숨김파일 볼 수 있음

## 3. Remote Repository 생성 및 등록
1. 일단 깃헙에서 Private Repository 생성하기
![](https://velog.velcdn.com/images/sss_yeonii/post/7aed2b9e-8d5f-40dd-ae11-3fd63df0b988/image.png)
- README file
  - 프로젝트에 대한 설명, 사용방법, 라이센스, 설치방법 등에 대한 내용을 기술하는 파일
  - 나, 직장동료, 프로그램 사용자(테스터)를 위해 존재
- .gitignore
  - Git 버전 관리에서 제외할 파일 목록을 지정하는 파일 (모든 파일을 한번에 올릴 때 여기에 있는 파일들은 제외시켜줌)
  - 사용자가 원하지 않는 파일들을 자동으로 commit 대상에서 제외시켜 줌
  - VS code에서 회색 처리됨 
2. github token 생성 (보안상 Remote Repository 접속 시 비밀번호 대신 token 사용)
  - Settings &gt; Developer settings &gt; Personal access tokens &gt; classic
  - 여기에서 token 생성하고 나면 다시 확인할 수 없으니까 잘 저장해두기!
3. Local Repository에 연동할 Remote Repository 등록 (token 사용) 
![](https://velog.velcdn.com/images/sss_yeonii/post/c91bc37f-b6ca-4902-a128-569ad1a26ae3/image.png)
- Remote Repository에서 HTTPS의 주소를 복사
- `git remote add origin https://&lt;username&gt;:&lt;token&gt;@github.com/&lt;repository&gt;.git`
  - 여기에서 `&lt;username&gt;:&lt;token&gt;`을 함께 입력해주면 remote repository에 push, pull할 때 username과 token을 물어보지 않고 자동으로 입력해서 편리함.
- `git remote -v`로 remote repository 연결 여부 확인

## 4. Remote Repository에 변경 내용 Push하고, Pull 해오기 ⭐️⭐️
1. `git push origin master`
  - 오류 뜨면 `git push origin main` (예전에는 master 썼는데 요즘에는 main으로 바뀜)
  - git에 push할 건데 현재 연결된 Remote Repository인 origin의 master Branch에 할 것이다 라는 의미
  - commit 했던 변경 내용을 master branch에 push
2. Remote Repository에서 Push된 파일 확인
![](https://velog.velcdn.com/images/sss_yeonii/post/db42046a-b008-4c20-a3cd-16b1a40d614b/image.png)
3. `git pull origin &lt;branchname: main 등&gt;`
- (Github에서 ReadMe 파일 추가했었음) -&gt; Readme 파일을 Local Repository로 Pull 
- `ls` 했을 때, README.md test.txt 로 추가된 것 확인할 수 있음.
- (참고) `cat exam.txt` 와 같이 입력하면 파일을 읽어옴


## 5. Remote Repository 복제하기 (git clone) ⭐️⭐️⭐️
- Local Repository 생성하지 않은 상태에서 git clone 명령으로 Remote Repository을 local에 복제하기
- `git clone https://&lt;username&gt;:&lt;token&gt;@github.com/&lt;repository&gt;.git`
  - 위 명령어로 폴더 생성 -&gt; git init(해당 폴더 초기화) -&gt; Remote Repository 등록 -&gt; Remote Repository 내용을 pull 과정을 모두 할 수 있음.
  - git clone 이후, Remote Repository 이름의 폴더가 생성되고, REAME.md나 .gitignore 파일이 가져와진 것을 확인할 수 있음</code></pre><p>  ~/git_ws $ git clone <a href="https://ssuyeonlee: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@github.com/ssuyeonlee/HelloGit.git">https://ssuyeonlee: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@github.com/ssuyeonlee/HelloGit.git</a>
  Cloning into &#39;HelloGit&#39;...
  remote: Enumerating objects: 4, done.
  remote: Counting objects: 100% (4/4), done.
  remote: Compressing objects: 100% (3/3), done.
  remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
  Receiving objects: 100% (4/4), done.</p>
<p>  ~/git_ws $ cd HelloGit</p>
<p>  ~/git_ws/HelloGit $ ls -all
  total 16
  drwxr-xr-x   5 sy  staff   160  9  7 16:33 .
  drwxr-xr-x   6 sy  staff   192  9  7 16:33 ..
  drwxr-xr-x  12 sy  staff   384  9  7 16:33 .git
  -rw-r--r--   1 sy  staff  3139  9  7 16:33 .gitignore
  -rw-r--r--   1 sy  staff    10  9  7 16:33 README.md</p>
<pre><code>
## 6. Branch
### Branch 조회
- `git branch` Local에 있는 branch 조회
- `git branch -r` Remote에 있는 branch 조회
- `git branch -a` Local+Remote에 있는 branch 모두 조회
  - `q`로 빠져나오기
```shell
$ git branch -a
* main   # *: 현재 위치한 branch가 어디인지 나타냄
  remotes/origin/HEAD -&gt; origin/main
  remotes/origin/main</code></pre><h3 id="branch-생성">Branch 생성</h3>
<p><code>git branch &lt;branchname&gt;</code> </p>
<ul>
<li>이렇게 하면 branchname의 branch가 하나 더 생성됨</li>
<li>이때 생성한 branch는 현재 위치한 branch인 main과 동일한 파일들로 구성됨. 복제가 된다는 뜻.<h3 id="branch-이동">Branch 이동</h3>
<code>git checkout &lt;branchname&gt;</code></li>
</ul>
<h3 id="branch-생성과-이동을-동시에-하는-방법-⭐️">Branch 생성과 이동을 동시에 하는 방법 ⭐️</h3>
<p><code>git checkout -b &lt;branchname&gt;</code></p>
<ul>
<li>-b : branch</li>
<li>branchname이 없어야만 오류가 뜨지 않음.</li>
</ul>
<h3 id="생성한-branch를-remote-repository에-올리기">생성한 Branch를 Remote Repository에 올리기</h3>
<p><code>git push origin &lt;branchname&gt;</code></p>
<h3 id="branch-삭제local">Branch 삭제(Local)</h3>
<p><code>git branch -d &lt;branchname&gt;</code></p>
<ul>
<li>-d: delete<h3 id="branch-삭제remote">Branch 삭제(Remote)</h3>
<code>git push origin --delete &lt;branchname&gt;</code></li>
</ul>
<h2 id="7-git-log-and-diff">7. Git Log and Diff</h2>
<h3 id="vs-code의-git-graph-extension">VS Code의 git graph extension</h3>
<ul>
<li><p>git graph extension 설치하기</p>
</li>
<li><p>사용 중인 git에서 로그들을 시각화하여 확인할 수 있음.
<img src="https://velog.velcdn.com/images/sss_yeonii/post/ad87a970-1468-4294-ae54-863d6fcff595/image.png" alt=""></p>
</li>
<li><p>좌측 3번째 메뉴 클릭 &gt; SOURCE CONTROL 우측 4번째 branch같은 아이콘 클릭</p>
</li>
<li><p>사실 터미널에서 <code>git log</code>로 해당 git에서 있었던 로그들도 확인 가능 (나갈 때는 <code>q</code> 입력)
<img src="https://velog.velcdn.com/images/sss_yeonii/post/22c76a6e-28cb-48c4-a917-a21dc1a980e8/image.png" alt=""></p>
</li>
</ul>
<h3 id="git-editor-설정">Git Editor 설정</h3>
<p><code>git config --global core.editor &lt;editorname&gt; --wait</code></p>
<ul>
<li>global 설정으로 기본 Git editor를 설정할 수 있음
-- editor로는 vim, VS Code 설정 가능</li>
<li>--wait 옵션은 command line으로 VS Code를 실행시켰을 경우, VS Code 인스턴스를 닫을 때까지 command를 대기하는 것. 그게 싫으면 제외해서 설정하면 됨.</li>
</ul>
<h3 id="git-diff-tool-설정">Git Diff Tool 설정</h3>
<p><code>git config --global -e</code></p>
<ul>
<li>editor를 VS Code로 했으면, 파일이 VS Code로 열림 </li>
</ul>
<pre><code class="language-shell">[core]
    autocrlf = input
    editor = code --wait

[diff]
    tool = vscode
[difftool &quot;vscode&quot;]
    cmd = &quot;code --wait --diff $LOCAL $REMOTE&quot;</code></pre>
<ul>
<li>[core]에서 code(=vs code)가 wait 옵션과 함께 설정되어 있음.</li>
<li>[diff], [difftool &quot;vscode&quot;] 추가</li>
</ul>
<h3 id="git-diff---local-branch-간-비교">Git Diff - Local Branch 간 비교</h3>
<p><code>git diff &lt;branch1&gt; &lt;branch2&gt;</code></p>
<ul>
<li>diff: vim을 사용해서 branch 간에 비교
<code>git difftool &lt;branch1&gt; &lt;branch2&gt;</code></li>
<li>difftool 하면, 기본 editor인 VS Code 실행하여 확인할지 여부 확인 
-&gt; Launch &#39;vscode&#39; [Y/n]? 에서 Y 입력</li>
<li>VS Code에서 두 Branch 간의 차이를 아래와 같이 시각화 된 결과로 비교할 수 있음
<img src="https://velog.velcdn.com/images/sss_yeonii/post/01a727c4-e0f4-4eb1-9ae6-e9d67e5c586a/image.png" alt=""></li>
</ul>
<h3 id="git-diff---commit-간-비교">Git Diff - Commit 간 비교</h3>
<p><code>git difftool &lt;commithash&gt; &lt;commithash&gt;</code></p>
<ul>
<li>그 전에, Commit Hashcode는 <code>git log</code>에서 각 commit별 뒤의 문자열
<img src="https://velog.velcdn.com/images/sss_yeonii/post/ba98d327-8779-405b-9800-e2839e1dc24c/image.png" alt=""></li>
<li><blockquote>
<p>위와 같이 commit 뒤의 문자열 복사</p>
</blockquote>
</li>
<li><blockquote>
<p><code>git difftool 2c5a4faa4a9bf99e8cf2cdbc4e7ccbe8d5f40261 374c98f8129ec5a8b2db09b93f611d5eacb6dcd6</code> 실행</p>
</blockquote>
</li>
<li><blockquote>
<p>VS Code에서 변경사항 비교
<img src="https://velog.velcdn.com/images/sss_yeonii/post/3b18f551-9607-403e-b2d7-745a5a2b8d79/image.png" alt=""></p>
</blockquote>
</li>
</ul>
<h3 id="git-diff---마지막-commit과-이전-commit-비교">Git Diff - 마지막 Commit과 이전 Commit 비교</h3>
<p><code>git difftool HEAD HEAD^</code> (여기까지 잘 확인하지는 않긴 함)</p>
<ul>
<li>HEAD^: 마지막 바로 직전 commit</li>
</ul>
<h3 id="git-diff---마지막-commit과-현재-수정사항-확인">Git Diff - 마지막 Commit과 현재 수정사항 확인</h3>
<p><code>git difftool HEAD</code></p>
<ul>
<li>최근 수정하여 올린 commit과 아직 commit하기 이전인 현재의 수정 사항 간의 차이점 비교</li>
</ul>
<h3 id="git-diff---local과-remote-간-비교">Git Diff - Local과 Remote 간 비교</h3>
<p><code>git diff &lt;branch&gt; origin/&lt;branch2&gt;</code> </p>
<ul>
<li><code>origin/&lt;branch2&gt;</code>: Remote Repository를 의미하는 origin에서의 어떤 branch와 비교할지를 입력하는 부분</li>
</ul>
<h2 id="8-merge-and-conflict">8. Merge and Conflict</h2>
<h3 id="merge-tool-설정">Merge Tool 설정</h3>
<p><code>git config --global -e</code> 실행하여 아래 내용을 최하단에 추가</p>
<pre><code>[merge]
    tool = vscode
[mergetool &quot;vscode&quot;]
    cmd = &quot;code --wait $MERGED&quot;</code></pre><h3 id="git-merge">Git Merge</h3>
<p><code>git merge &lt;branchname&gt;</code></p>
<ul>
<li>현재 위치한 Branch에 다른 Branch를 병합</li>
</ul>
<h3 id="merge-conflict">Merge Conflict</h3>
<ul>
<li>Branch Merge 과정에서 발생하는 충돌. Push, pull할 때도 충돌 일어날 수 있음.</li>
<li>main의 test.txt 내용과 dev2의 test.txt 내용이 다를 때, main에서 git merge dev를 하게 되면? 아래와 같이 CONFLICT 발생<pre><code>$ git merge dev2
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.</code></pre></li>
<li><code>git mergetool</code>을 사용하여 해결해보자!<ul>
<li>충돌이 발생한 파일이 순차적으로 나옴 
<img src="https://velog.velcdn.com/images/sss_yeonii/post/b574af29-6b6a-4fe6-b680-7da8f8c65c25/image.png" alt=""></li>
<li>둘 중에 어떤 내용으로 merge할지를 선택하고, 그 내용만 파일에 남겨둔다. </li>
<li>저장 후 VS Code 종료
<img src="https://velog.velcdn.com/images/sss_yeonii/post/6d00b89d-428d-435b-8cac-c3c2a8411db3/image.png" alt=""></li>
</ul>
</li>
<li>파일만 수정이 된 상태라 다시 merge 시도하면 여전히 CONFLICT 상태임<pre><code>git merge dev2
fatal: You have not concluded your merge (MERGE_HEAD exists).
Please, commit your changes before you merge.</code></pre></li>
<li>Conflict 해제<ul>
<li>git add +  git commit 
<img src="https://velog.velcdn.com/images/sss_yeonii/post/c01d3d10-ded9-4496-8232-f24035eeed7c/image.png" alt=""></li>
<li>VS Code가 열리면 저장하고 닫기
<img src="https://velog.velcdn.com/images/sss_yeonii/post/40088906-ba12-4d69-97c4-48b0a48b9902/image.png" alt=""></li>
</ul>
</li>
<li>터미널에서 Merge된 것을 확인할 수 있음
<img src="https://velog.velcdn.com/images/sss_yeonii/post/00337280-3436-4a1b-9237-035337dd5064/image.png" alt=""></li>
<li>git log로 확인
<img src="https://velog.velcdn.com/images/sss_yeonii/post/5529265a-0d9b-4d36-a0c9-cd11a6acbb6e/image.png" alt=""></li>
</ul>
<h2 id="9-git-tag">9. Git Tag</h2>
<ul>
<li>Tag: 특정 버전(commit)에 Tag를 달아놓을 필요가 있을 때 사용(e.g. 버전 릴리즈, 큰 변경사항이 있을 때)</li>
<li><code>git tag &lt;tagname&gt;</code>: Local에서 마지막 버전(commit)에 tag 달기
<img src="https://velog.velcdn.com/images/sss_yeonii/post/1ba144fa-931a-47c6-b363-09e46874f40b/image.png" alt=""></li>
<li><code>git tag &lt;tagname&gt; &lt;commithash&gt;</code>: Local에서 특정 버전(commit)에 tag 달기 -&gt; commit 2에 tag 달림
<img src="https://velog.velcdn.com/images/sss_yeonii/post/5bff5b3d-f499-4fea-992d-4b68e4da67be/image.png" alt=""></li>
<li><code>git push origin &lt;tagname&gt;</code>: Local에서 위와 같이 달았던 Tag를 Remote에도 반영해야 할 때 Tag를 push해줌.<ul>
<li>github 가보면 Tag 달려있음 
<img src="https://velog.velcdn.com/images/sss_yeonii/post/e4147737-8f17-4728-9b0b-baf731fc235e/image.png" alt="">
<img src="https://velog.velcdn.com/images/sss_yeonii/post/40e3e60a-ee77-415e-a8e3-342a126db604/image.png" alt=""></li>
</ul>
</li>
<li><code>git tag</code>: 현재까지 Local에서 설정한 tag 목록 보기</li>
<li><code>git show &lt;tagname&gt;</code>: tag의 상세 정보 확인하기</li>
<li><code>git tag --delete &lt;tagname&gt;</code>: Local의 tag 삭제</li>
<li><code>git push --delete origin &lt;tagname&gt;</code>: Remote의 tag 삭제 (Remote에서만 삭제하고 Local에서는 삭제하지 않을 때도 이것만 실행하면 됨)</li>
</ul>
<h3 id="참고">참고</h3>
<ul>
<li><p><code>cat 파일명</code>: 파일을 읽어옴</p>
</li>
<li><p><code>cat &gt; 파일명</code>: 파일이 존재하면 파일의 내용을 입력하는 값으로 덮어씌움. 파일이 존재하지 않는다면 입력하는 값으로 파일을 생성함. 내용 입력 후 엔터. 모두 다 입력했으면 control+d로 완료하기.</p>
</li>
<li><p><code>cat &gt;&gt; 파일명</code>: &gt;&gt;를 쓰면 덮어씌우지 않고 밑줄에 이어서 내용이 추가됨. </p>
</li>
<li><p><code>code .</code> 현재 위치에서 VSCode 열기 </p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[터미널 자주 쓰이는 용어]]></title>
            <link>https://velog.io/@sss_yeonii/%ED%84%B0%EB%AF%B8%EB%84%90-%EC%9E%90%EC%A3%BC-%EC%93%B0%EC%9D%B4%EB%8A%94-%EC%9A%A9%EC%96%B4</link>
            <guid>https://velog.io/@sss_yeonii/%ED%84%B0%EB%AF%B8%EB%84%90-%EC%9E%90%EC%A3%BC-%EC%93%B0%EC%9D%B4%EB%8A%94-%EC%9A%A9%EC%96%B4</guid>
            <pubDate>Thu, 29 Aug 2024 03:06:48 GMT</pubDate>
            <description><![CDATA[<h3 id="터미널-자주-쓰이는-용어">터미널 자주 쓰이는 용어</h3>
<ol>
<li><code>cd {폴더경로 e.g. opt/project/~}</code> 디렉토리 이동 <ol>
<li><code>cd ..</code> 상위 폴더로 현재 위치 이동 </li>
<li><code>cd /</code> 최상위 폴더로 돌아가기</li>
</ol>
</li>
<li><code>pwd</code> 현재 경로 위치 출력</li>
<li><code>ls -al</code> 현재 디렉토리에서 파일 리스트 전체 자세히 출력 <ol>
<li><code>ls</code> 현재 디렉토리 안에 있는 파일 확인</li>
</ol>
</li>
<li><code>mkdir {폴더명}</code> 폴더 생성</li>
<li><code>rmdir {폴더명}</code> 폴더 삭제 <ol>
<li><code>rm  -r suyeon</code> 혹은 이렇게도 가능</li>
</ol>
</li>
<li><code>clear</code> 터미널 정리 </li>
<li><code>cp</code> (파일 복사)</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[matplotlib.pyplot의plt.style.use() 사용하는 방법]]></title>
            <link>https://velog.io/@sss_yeonii/matplotlib.pyplot%EC%9D%98plt.style.use-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@sss_yeonii/matplotlib.pyplot%EC%9D%98plt.style.use-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Sun, 18 Aug 2024 05:56:09 GMT</pubDate>
            <description><![CDATA[<p>matplotlib이 제공하는 <code>mpl.style.use(&#39;seaborn~&#39;)</code>이 deprecated되었다.
대신, matplotlib.pyplot의 <code>plt.style.use()</code>를 사용하면 된다. </p>
<p>사용할 수 있는 style 목록:</p>
<pre><code class="language-python">import matplotlib.pyplot as plt
plt.style.available
...
[&#39;Solarize_Light2&#39;,
 &#39;_classic_test_patch&#39;,
 &#39;_mpl-gallery&#39;,
 &#39;_mpl-gallery-nogrid&#39;,
 &#39;bmh&#39;,
 &#39;classic&#39;,
 &#39;dark_background&#39;,
 &#39;fast&#39;,
 &#39;fivethirtyeight&#39;,
 &#39;ggplot&#39;,
 &#39;grayscale&#39;,
 &#39;seaborn-v0_8&#39;,
 &#39;seaborn-v0_8-bright&#39;,
 &#39;seaborn-v0_8-colorblind&#39;,
 &#39;seaborn-v0_8-dark&#39;,
 &#39;seaborn-v0_8-dark-palette&#39;,
 &#39;seaborn-v0_8-darkgrid&#39;,
 &#39;seaborn-v0_8-deep&#39;,
 &#39;seaborn-v0_8-muted&#39;,
 &#39;seaborn-v0_8-notebook&#39;,
 &#39;seaborn-v0_8-paper&#39;,
 &#39;seaborn-v0_8-pastel&#39;,
 &#39;seaborn-v0_8-poster&#39;,
 &#39;seaborn-v0_8-talk&#39;,
 &#39;seaborn-v0_8-ticks&#39;,
 &#39;seaborn-v0_8-white&#39;,
 &#39;seaborn-v0_8-whitegrid&#39;,
 &#39;tableau-colorblind10&#39;]</code></pre>
<p>이런 식으로 사용하면 된다.</p>
<pre><code class="language-python">plt.style.use(&#39;ggplot&#39;)
plt.figure(figsize=(12,8))
plt.xlabel(&#39;$x$&#39;)
plt.ylabel(&#39;$y = 3x^2 +2$&#39;)
plt.plot(x, y);</code></pre>
<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/d59f8754-a61c-4c6f-ae44-e97397a18e96/image.png" alt=""></p>
<p>출처: <a href="https://stackoverflow.com/questions/74716259/the-seaborn-styles-shipped-by-matplotlib-are-deprecated-since-3-6">https://stackoverflow.com/questions/74716259/the-seaborn-styles-shipped-by-matplotlib-are-deprecated-since-3-6</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Subquery(서브쿼리)]]></title>
            <link>https://velog.io/@sss_yeonii/Subquery%EC%84%9C%EB%B8%8C%EC%BF%BC%EB%A6%AC</link>
            <guid>https://velog.io/@sss_yeonii/Subquery%EC%84%9C%EB%B8%8C%EC%BF%BC%EB%A6%AC</guid>
            <pubDate>Fri, 09 Aug 2024 08:54:05 GMT</pubDate>
            <description><![CDATA[<h1 id="subquery서브쿼리">Subquery(서브쿼리)</h1>
<ul>
<li>Subquery(서브쿼리): 하나의 SQL문 안에 포함되어 있는 또 다른 SQL문을 말한다.</li>
<li>메인쿼리가 서브쿼리를 포함하는 종속적인 관계이다.<ul>
<li>서브쿼리는 메인 쿼리의 칼럼 사용 가능</li>
<li>메인쿼리는 서브쿼리의 칼럼 사용 불가</li>
</ul>
</li>
<li>서브쿼리 사용 시 주의점<ul>
<li>서브쿼리는 괄호로 묶어서 사용</li>
<li>단일 행 또는 복수 행 비교 연산자와 함께 사용 가능</li>
<li>Subquery 에서는 Order By 사용 X</li>
</ul>
</li>
<li>서브쿼리 종류<ul>
<li>Scalar Subquery(스칼라 서브쿼리): SELECT절에 사용</li>
<li>Inline View(인라인뷰): FROM절에 사용</li>
<li>Nested Subquery(중첩 서브쿼리): WHERE절에 사용</li>
</ul>
</li>
</ul>
<h2 id="scalar-subquery스칼라-서브쿼리-select절에-사용">Scalar Subquery(스칼라 서브쿼리): SELECT절에 사용</h2>
<ul>
<li>결과는 하나의 Column이어야 한다. <pre><code class="language-sql">SELECT col1, (SELECT col2 FROM table2 WHERE condition)
FROM table1
WHERE condition</code></pre>
</li>
<li>예제: 서울은평경찰서의 강도 검거 건수와 서울시 경찰서 전체의 평균강도검거건수를 조회
```sql
mysql&gt; select case_number,
  -&gt; (select avg(case_number)
  -&gt; from crime_status
  -&gt; where crime_type=&#39;강도&#39; and status_type like &#39;검거&#39;) avg
  -&gt; from crime_status
  -&gt; where police_station like &#39;은평&#39; and crime_type like &#39;강도&#39; and status_type like &#39;검거&#39;;</li>
<li>-------------+--------+
| case_number | avg    |</li>
<li>-------------+--------+
|           1 | 4.1935 |</li>
<li>-------------+--------+
1 row in set (0.02 sec)<pre><code>
</code></pre></li>
</ul>
<h2 id="inline-view인라인뷰-from절에-사용">Inline View(인라인뷰): FROM절에 사용</h2>
<ul>
<li>메인쿼리에서는 인라인 뷰에서 조회한 Column만 사용 가능<pre><code class="language-sql">SELECT a.column, b.column
FROM table1 a, (SELECT col1, col2 FROM table2) b
WHERE condition</code></pre>
</li>
<li>예제: 경찰서별 가장 많이 발생한 범죄 건수와 이때의 범죄 유형을 조회<pre><code class="language-sql">SELECT c.police_station, c.crime_type, c.case_number
FROM crime_status c, 
  (SELECT police_station, max(case_number) count
   FROM crime_status
   WHERE status_type LIKE &#39;발생&#39;
   GROUP BY police_station) m
WHERE c.police_station = m.police_station
  AND c.case_number = m.count 
</code></pre>
</li>
</ul>
<p>mysql&gt; SELECT c.police_station, c.crime_type, c.case_number
    -&gt; FROM crime_status c, 
    -&gt; (SELECT police_station, max(case_number) count
    -&gt;      FROM crime_status
    -&gt;      WHERE status_type LIKE &#39;발생&#39;
    -&gt;      GROUP BY police_station) m
    -&gt; WHERE c.police_station = m.police_station
    -&gt; AND c.case_number = m.count ;
+----------------+------------+-------------+
| police_station | crime_type | case_number |
+----------------+------------+-------------+
| 중부           | 폭력       |         997 |
| 종로           | 폭력       |         964 |
| 남대문         | 절도       |         699 |
| 서대문         | 폭력       |        1292 |
| 혜화           | 폭력       |         747 |
| 용산           | 폭력       |        1617 |
| 성북           | 폭력       |         672 |
| 동대문         | 폭력       |        1784 |
| 마포           | 폭력       |        1844 |
| 영등포         | 폭력       |        2701 |
| 성동           | 폭력       |        1223 |
| 동작           | 폭력       |        1631 |
| 광진           | 폭력       |        1676 |
| 서부           | 폭력       |         748 |
| 강북           | 폭력       |        1817 |
| 금천           | 폭력       |        1471 |
| 중랑           | 폭력       |        2022 |
| 강남           | 폭력       |        2283 |
| 관악           | 폭력       |        2614 |
| 강서           | 폭력       |        2445 |
| 강동           | 폭력       |        1942 |
| 종암           | 폭력       |         758 |
| 구로           | 폭력       |        2204 |
| 서초           | 폭력       |        1750 |
| 양천           | 폭력       |        1582 |
| 송파           | 폭력       |        2675 |
| 노원           | 폭력       |        2163 |
| 방배           | 폭력       |         423 |
| 은평           | 폭력       |        1092 |
| 도봉           | 폭력       |        1234 |
| 수서           | 폭력       |        1394 |
+----------------+------------+-------------+
31 rows in set (0.02 sec)</p>
<pre><code>## Nested Subquery(중첩 서브쿼리): WHERE절에 사용
### Single Row: 하나의 행을 검색하는 서브쿼리
- 서브쿼리가 비교연산자(=, &gt;, &gt;=, &lt;, &lt;=, &lt;&gt;, !=)와 사용되는 경우, 서브쿼리의 검색 결과는 한 개의 결과값을 가져야 한다. (두개 이상인 경우 에러)
```sql
SELECT col_name
FROM tablename
WHERE col_name = (SELECT col_name //이것의 결과값이 딱 하나여야 함. 
                  FROM tablename
                  WHERE condition)   

mysql&gt; select name from celeb where name = (select host from snl_show);
ERROR 1242 (21000): Subquery returns more than 1 row
// 비교연산자 &#39;=&#39;를 사용했을 때, 아래와 같이 서브쿼리의 결과가 한 개 이상이기 때문에 에러가 발생

mysql&gt; select host from snl_show;
+-----------+
| host      |
+-----------+
| 강동원    |
| 유재석    |
| 차승원    |
| 이수현    |
| 이병헌    |
| 하지원    |
| 제시      |
| 조정석    |
| 조여정    |
| 옥주현    |
+-----------+
10 rows in set (0.02 sec)

// 특정 id를 지정해서 하나의 결과만 가져오도록 하면 에러가 발생하지 않음.
mysql&gt; select name from celeb where name = (select host from snl_show where id =1);
+-----------+
| name      |
+-----------+
| 강동원    |
+-----------+
1 row in set (0.02 sec)
</code></pre><h3 id="multiple-row-하나-이상의-행을-검색하는-서브쿼리">Multiple Row: 하나 이상의 행을 검색하는 서브쿼리</h3>
<h4 id="in">IN</h4>
<ul>
<li>서브쿼리 결과 중에 포함될 때: IN 을 사용한 서브쿼리
```sql
SELECT col_name
FROM tablename
WHERE col_name IN (SELECT col_name //이것의 결과값이 딱 하나여야 함. <pre><code>             FROM tablename
             WHERE condition)</code></pre>// SNL에 출연한 영화배우를 조회
mysql&gt; select host
  -&gt; from snl_show
  -&gt; where host in (select name
  -&gt;                   from celeb
  -&gt;                   where job_title like &#39;%영화배우%&#39;);</li>
<li>-----------+
| host      |</li>
<li>-----------+
| 강동원    |
| 차승원    |</li>
<li>-----------+
2 rows in set (0.02 sec)
```<h4 id="exists">EXISTS</h4>
</li>
<li>EXISTS: 서브쿼리 결과에 값이 있으면 반환
// 범죄 검거 혹은 발생 건수가 2000건 보다 큰 경찰서 조회
```sql
select name
from police_station p
where exists (select police_station<pre><code>        from crime_status c
        where p.name = c.reference and case_number &gt; 2000);</code></pre>select reference
from crime_status
where case_number &gt; 2000);</li>
<li>--------------------------+
| name                     |</li>
<li>--------------------------+
| 서울강남경찰서           |
| 서울강서경찰서           |
| 서울관악경찰서           |
| 서울구로경찰서           |
| 서울노원경찰서           |
| 서울송파경찰서           |
| 서울영등포경찰서         |
| 서울중랑경찰서           |</li>
<li>--------------------------+
8 rows in set (0.02 sec)
```<h4 id="any">ANY</h4>
</li>
<li>ANY: 서브쿼리 결과 중에 최소한 하나라도 만족하면 (비교연산자 사용)</li>
<li>IN과 다른 점은, 비교 연산자와 함께 사용이 가능하다는 점 <ul>
<li>&#39;=ANY (Subquery)&#39;는 &#39;IN (Subquery)&#39;와 동일함.
```sql
select name
from celeb
where name = ANY (select host<pre><code>          from snl_show);</code></pre></li>
</ul>
</li>
<li>-----------+
| name      |</li>
<li>-----------+
| 강동원    |
| 유재석    |
| 차승원    |
| 이수현    |</li>
<li>-----------+
4 rows in set (0.01 sec)
```<h4 id="all">All</h4>
</li>
<li>All: 서브쿼리 결과를 모두 만족하면 (비교연산자 사용)
```sql
select name
from celeb
where name = ANY (select host<pre><code>             from snl_show
            where id = 1);</code></pre></li>
<li>-----------+
| name      |</li>
<li>-----------+
| 강동원    |</li>
<li>-----------+
1 row in set (0.01 sec)<pre><code></code></pre></li>
</ul>
<h3 id="multiple-column-서브쿼리연관-서브쿼리-하나-이상의-열을-검색하는-서브쿼리">Multiple Column 서브쿼리(연관 서브쿼리): 하나 이상의 열을 검색하는 서브쿼리</h3>
<ul>
<li>서브쿼리 내에 메인쿼리 컬럼이 같이 사용되는 경우<pre><code class="language-sql">select column_names
from tablename a
where (a.col1, a.col2, ...) IN (select b.col1, b.col2, ...
                              from tablename b
                              where a.column_name = b.column_name);
</code></pre>
</li>
</ul>
<p>// 강동원과 성별, 소속사가 같은 연예인의 이름, 성별, 소속사를 조회
mysql&gt; select name, sex, agency
    -&gt; from celeb
    -&gt; where (sex, agency) in (select sex, agency from celeb where name = &#39;강동원&#39;);
+-----------+------+----------------------+
| name      | sex  | agency               |
+-----------+------+----------------------+
| 강동원    | M    | YG엔터테인먼트       |
| 차승원    | M    | YG엔터테인먼트       |
+-----------+------+----------------------+
2 rows in set (0.02 sec)</p>
<pre><code>#### 실습 예제
```sql
//1. oil_price 테이블에서 셀프주유의 평균가격과 SK에너지의 가장 비싼 가격을 Scalar Query를 사용하여 조회
mysql&gt; select avg(가격) 셀프주유평균가격, (select max(가격) from oil_price where 상표 like &#39;%SK%&#39;)  SK최고가격  from oil_price where 셀프=&#39;Y&#39;;
+--------------------------+----------------+
| 셀프주유평균가격         | SK최고가격     |
+--------------------------+----------------+
|                1517.6000 |           2160 |
+--------------------------+----------------+
1 row in set (0.07 sec)

//2. oil_price 테이블에서 상표별로 가장 비싼 가격과 상호를 Inline View를 사용하여 조회하세요. 
mysql&gt; select o.상호, o.상표, m.max_price 
       from oil_price o, (
            select 상표, max(가격) max_price 
            from oil_price group by 상표
            ) m 
       where o.상표=m.상표 and o.가격=m.max_price;
+-------------------+--------------------+-----------+
| 상호              | 상표               | max_price |
+-------------------+--------------------+-----------+
| (주)MS주유소      | 현대오일뱅크       |      1498 |
| 쌍문주유소        | S-OIL              |      1509 |
| 뉴서울(강남)      | SK에너지           |      2160 |
| 신길주유소        | GS칼텍스           |      1498 |
+-------------------+--------------------+-----------+
4 rows in set (0.06 sec)

//3. 평균가격보다 높은 주유소 상호와 가격을 Nested Subquery를 사용하여 조회하세요.
mysql&gt; select  상호, 가격 from oil_price where 가격 &gt; (select avg(가격) from oil_price);
+--------------------+--------+
| 상호               | 가격   |
+--------------------+--------+
| 21세기주유소       |   1598 |
| 살피재주유소       |   1635 |
| 뉴서울(강남)       |   2160 |
+--------------------+--------+
3 rows in set (0.07 sec)

//4. 3번에서 조회한 주유소에서 주유한 연예인의 이름과 주유소, 주유일을 Nested Query를 사용하여 조회하세요. (refueling 테이블)
mysql&gt; select 이름, 주유소, 주유일 from refueling where 주유소 in (select 상호 from oil_price where 가격 &gt; (select avg(가격) from oil_price));
+-----------+-------------------+------------+
| 이름      | 주유소            | 주유일     |
+-----------+-------------------+------------+
| 유재석    | 뉴서울(강남)      | 2021-10-01 |
| 이미주    | 뉴서울(강남)      | 2021-10-01 |
| 유재석    | 뉴서울(강남)      | 2021-10-03 |
| 아이유    | 뉴서울(강남)      | 2021-10-14 |
| 아이유    | 뉴서울(강남)      | 2021-10-14 |
| 유재석    | 뉴서울(강남)      | 2021-10-16 |
+-----------+-------------------+------------+
6 rows in set (0.20 sec)

// 내코드: 위처럼 in을 쓰면 더 간단하게 할 수 있구나..!
mysql&gt; select o.이름, o.주유소, o.주유일 from refueling o, (select  상호, 가격 from oil_price where 가격 &gt; (select avg(가격) from oil_price)) s where o.주유
소=s.상호;
+-----------+-------------------+------------+
| 이름      | 주유소            | 주유일     |
+-----------+-------------------+------------+
| 유재석    | 뉴서울(강남)      | 2021-10-01 |
| 이미주    | 뉴서울(강남)      | 2021-10-01 |
| 유재석    | 뉴서울(강남)      | 2021-10-03 |
| 아이유    | 뉴서울(강남)      | 2021-10-14 |
| 아이유    | 뉴서울(강남)      | 2021-10-14 |
| 유재석    | 뉴서울(강남)      | 2021-10-16 |
+-----------+-------------------+------------+
6 rows in set (0.06 sec)

// 5. refueling 테이블과 oil_price 테이블에서 10만원 이상 주유한 연예인 이름, 상호, 상표, 주유 금액, 가격을 Inline View를 사용하여 조회하세요. 
mysql&gt; select r.이름, r.주유소, r.금액, o.상표, o.가격 from oil_price o, 
    -&gt; (select 이름, 주유소, 금액 from refueling where 금액 &gt;= 100000) r
    -&gt; where o.상호=r.주유소;
+-----------+--------------------+--------+-------------+--------+
| 이름      | 주유소             | 금액   | 상표        | 가격   |
+-----------+--------------------+--------+-------------+--------+
| 이상순    | 타이거주유소       | 140000 | SK에너지    |   1484 |
| 유재석    | 뉴서울(강남)       | 110000 | SK에너지    |   2160 |
| 아이유    | 뉴서울(강남)       | 120000 | SK에너지    |   2160 |
| 아이유    | 뉴서울(강남)       | 150000 | SK에너지    |   2160 |
| 이미주    | 뉴서울(강남)       | 120000 | SK에너지    |   2160 |
+-----------+--------------------+--------+-------------+--------+
5 rows in set (0.07 sec)
// 내 풀이: 내꺼가 좀 더 간단한듯 ㅎ
mysql&gt; select r.이름, r.주유소, r.금액, o.상표, o.가격 from refueling r, oil_price o where r.금액&gt;100000 and o.상호=r.주유소;
+-----------+--------------------+--------+-------------+--------+
| 이름      | 주유소             | 금액   | 상표        | 가격   |
+-----------+--------------------+--------+-------------+--------+
| 이상순    | 타이거주유소       | 140000 | SK에너지    |   1484 |
| 유재석    | 뉴서울(강남)       | 110000 | SK에너지    |   2160 |
| 아이유    | 뉴서울(강남)       | 120000 | SK에너지    |   2160 |
| 아이유    | 뉴서울(강남)       | 150000 | SK에너지    |   2160 |
| 이미주    | 뉴서울(강남)       | 120000 | SK에너지    |   2160 |
+-----------+--------------------+--------+-------------+--------+
5 rows in set (0.04 sec)</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Scalar Functions(ucase, lcase, mid, length, round, now, format)]]></title>
            <link>https://velog.io/@sss_yeonii/Scalar-Functionsucase-lcase-mid-length-round-now-format</link>
            <guid>https://velog.io/@sss_yeonii/Scalar-Functionsucase-lcase-mid-length-round-now-format</guid>
            <pubDate>Thu, 08 Aug 2024 12:36:26 GMT</pubDate>
            <description><![CDATA[<h1 id="scalar-funtions">Scalar Funtions</h1>
<ul>
<li>입력값을 기준으로 단일 값을 반환 하는 함수
<img src="https://velog.velcdn.com/images/sss_yeonii/post/023e0243-2b65-4f48-9cec-dcf328b87066/image.png" alt=""><h2 id="1-ucase대문자--lcase소문자">1. ucase(대문자) &amp; lcase(소문자)</h2>
```sql
mysql&gt; select ucase(&#39;This is ucase test.&#39;);</li>
<li>------------------------------+
| ucase(&#39;This is ucase test.&#39;) |</li>
<li>------------------------------+
| THIS IS UCASE TEST.          |</li>
<li>------------------------------+
1 row in set (0.01 sec)</li>
</ul>
<p>mysql&gt; select ucase(menu) from sandwich where price &gt; 15;
+----------------------------------+
| ucase(menu)                      |
+----------------------------------+
| LOBSTER ROLL                     |
| GRILLED LAUGHING BIRD SHRIMP AND |
| SHAVED PRIME RIB                 |
+----------------------------------+
3 rows in set (0.01 sec)</p>
<p>mysql&gt; select lcase(menu) from sandwich where price &gt;15;
+----------------------------------+
| lcase(menu)                      |
+----------------------------------+
| lobster roll                     |
| grilled laughing bird shrimp and |
| shaved prime rib                 |
+----------------------------------+
3 rows in set (0.02 sec)</p>
<pre><code>## 2. MID(대상값, 시작, 끝)
- 특정 위치의 문자열 반환
```sql
mysql&gt; select mid(&quot;This is mid test.&quot;, 1, 4);
+--------------------------------+
| mid(&quot;This is mid test.&quot;, 1, 4) |
+--------------------------------+
| This                           |
+--------------------------------+
1 row in set (0.02 sec)

mysql&gt; select mid(&quot;This is mid test.&quot;, 6, 5);
+--------------------------------+
| mid(&quot;This is mid test.&quot;, 6, 5) |
+--------------------------------+
| is mi                          |
+--------------------------------+
1 row in set (0.01 sec)

mysql&gt; select mid(&quot;This is mid test.&quot;, -4, 4);
+---------------------------------+
| mid(&quot;This is mid test.&quot;, -4, 4) |
+---------------------------------+
| est.                            |
+---------------------------------+
1 row in set (0.01 sec)

// 11위 카페 이름 중 두번째 단어만 조회
mysql&gt; select cafe from sandwich where ranking=11;
+-----------+
| cafe      |
+-----------+
| Lula Cafe |
+-----------+
1 row in set (0.02 sec)

mysql&gt; select mid(cafe, 6, 4) from sandwich where ranking=11;
+-----------------+
| mid(cafe, 6, 4) |
+-----------------+
| Cafe            |
+-----------------+
1 row in set (0.01 sec)

mysql&gt; select mid(cafe, -4, 4) from sandwich where ranking=11;
+------------------+
| mid(cafe, -4, 4) |
+------------------+
| Cafe             |
+------------------+
1 row in set (0.01 sec)</code></pre><h2 id="3-length">3. Length</h2>
<ul>
<li>문자열 길이를 반환하는 함수</li>
<li>공백(&#39; &#39;)의 길이는 1, null의 길이는 그대로 null 반환
```sql
mysql&gt; select length(&#39;This is len test.&#39;);</li>
<li>-----------------------------+
| length(&#39;This is len test.&#39;) |</li>
<li>-----------------------------+
|                          17 |</li>
<li>-----------------------------+
1 row in set (0.17 sec)</li>
</ul>
<p>mysql&gt; select length(&#39;&#39;);
+------------+
| length(&#39;&#39;) |
+------------+
|          0 |
+------------+
1 row in set (0.06 sec)</p>
<p>mysql&gt; select length(&#39; &#39;);
+-------------+
| length(&#39; &#39;) |
+-------------+
|           1 |
+-------------+
1 row in set (0.01 sec)</p>
<p>mysql&gt; select length(null);
+--------------+
| length(null) |
+--------------+
|         NULL |
+--------------+
1 row in set (0.02 sec)</p>
<p>// sandwich 테이블에서 top 3 주소 길이를 검색
mysql&gt; select ranking, address, length(address) from sandwich
    -&gt; where ranking &lt; 4;
+---------+---------------------+-----------------+
| ranking | address             | length(address) |
+---------+---------------------+-----------------+
|       1 | 2109 W. Chicago Ave |              19 |
|       2 | 800 W. Randolph St  |              18 |
|       3 |  445 N. Clark St    |              16 |
+---------+---------------------+-----------------+
3 rows in set (0.02 sec)</p>
<pre><code>
## 4. Round 
- 지정한 자리에서 숫자를 반올림하는 함수
- round(대상숫자, 반올림할 n번째 자릿수) 
- 디폴트 0: 소수점 첫번쨰 자리에서 반올림
```sql
mysql&gt; select round(123.987, 1);
+-------------------+
| round(123.987, 1) |
+-------------------+
|             124.0 |
+-------------------+
1 row in set (0.00 sec)

mysql&gt; select round(123.987, -1);
+--------------------+
| round(123.987, -1) |
+--------------------+
|                120 |
+--------------------+
1 row in set (0.01 sec)

// price를 1달러 단위까지만 반올림해서 표시(랭킹 최하위 3개만)
mysql&gt; select ranking, price, round(price)
    -&gt; from sandwich
    -&gt; order by ranking desc
    -&gt; limit 3;
+---------+-------+--------------+
| ranking | price | round(price) |
+---------+-------+--------------+
|      50 |  6.85 |            7 |
|      49 |  8.75 |            9 |
|      48 |   7.5 |            8 |
+---------+-------+--------------+
3 rows in set (0.02 sec)</code></pre><h2 id="5-now">5. now</h2>
<ul>
<li>현재 날짜 및 시간을 반환하는 함수
```sql
mysql&gt; select now();</li>
<li>---------------------+
| now()               |</li>
<li>---------------------+
| 2024-08-08 12:17:58 |</li>
<li>---------------------+
1 row in set (0.07 sec)
```<h2 id="6-format">6. format</h2>
</li>
<li>숫자를 천단위 콤마가 있는 형식으로 반환하는 함수
```sql
mysql&gt; select format(12345678.9876, 0);</li>
<li>--------------------------+
| format(12345678.9876, 0) |</li>
<li>--------------------------+
| 12,345,679               |</li>
<li>--------------------------+
1 row in set (0.01 sec)</li>
</ul>
<p>mysql&gt; select format(12345678.9876, 2);
+--------------------------+
| format(12345678.9876, 2) |
+--------------------------+
| 12,345,678.99            |
+--------------------------+
1 row in set (0.01 sec)</p>
<p>mysql&gt; select format(12345678.9876, 10);
+---------------------------+
| format(12345678.9876, 10) |
+---------------------------+
| 12,345,678.9876000000     |
+---------------------------+
1 row in set (0.03 sec)</p>
<p>// oil_price 테이블에서 백원 단위에서 가격을 반올림했을 때 2000원 이상인 경우 천원 단위에서 콤마를 넣어서 조회
mysql&gt; select format(가격, 0) from oil_price 
    -&gt; where round(가격, -3) &gt;= 2000;
+-------------------+
| format(가격, 0)   |
+-------------------+
| 1,509             |
| 1,598             |
| 1,635             |
| 2,160             |
+-------------------+
4 rows in set (0.01 sec)</p>
<pre><code>### 전체 실습 문제 풀이
```sql
1. sandwich 테이블에서 가게 이름은 대문자, 메뉴 이름은 소문자로 조회
mysql&gt; select ucase(cafe), lcase(menu) from sandwich limit 5;
+------------------------+-------------------+
| ucase(cafe)            | lcase(menu)       |
+------------------------+-------------------+
| OLD OAK TAP            | blt               |
| AU CHEVAL              | fried bologna     |
| XOCO                   | woodland mushroom |
| AL’S DELI              | roast beef        |
| PUBLICAN QUALITY MEATS | pb&amp;l              |
+------------------------+-------------------+
5 rows in set (0.02 sec)

2. sandwich 테이블에서 10위 메뉴의 마지막 단어를 조회하세요.
mysql&gt; select ranking, cafe, mid(menu, -3, 3) from sandwich where ranking=10;
+---------+------+------------------+
| ranking | cafe | mid(menu, -3, 3) |
+---------+------+------------------+
|      10 | Nana | and              |
+---------+------+------------------+
1 row in set (0.01 sec)

3. sandwich 테이블에서 메뉴 이름의 평균 길이를 조회하세요.
mysql&gt; select avg(length(menu)) from sandwich;
+-------------------+
| avg(length(menu)) |
+-------------------+
|           13.9600 |
+-------------------+
1 row in set (0.01 sec)


4. oil_price 테이블에서 가격을 십원 단위에서 반올림하여 조회하세요. 
mysql&gt; select 상호, 가격, round(가격, -2) from oil_price;
+----------------------+--------+-------------------+
| 상호                 | 가격   | round(가격, -2)   |
+----------------------+--------+-------------------+
| 타이거주유소         |   1484 |              1500 |
| (주)명연에너지       |   1485 |              1500 |
| 성락주유소           |   1498 |              1500 |
| (주)MS주유소         |   1498 |              1500 |
| 쌍문주유소           |   1509 |              1500 |
| 21세기주유소         |   1598 |              1600 |
| 살피재주유소         |   1635 |              1600 |
| 뉴서울(강남)         |   2160 |              2200 |
| 신길주유소           |   1498 |              1500 |
+----------------------+--------+-------------------+
9 rows in set (0.08 sec)

5. oil_price 테이블에서 가격이 십원 단위에서 반올림했을 때, 2000원 이상인 경우, 천 단위에 콤마를 넣어서 조회하세요. 

mysql&gt; select 상호, format(가격, 0) from oil_price
    -&gt; where round(가격, -2) &gt;= 2000;
+-------------------+-------------------+
| 상호              | format(가격, 0)   |
+-------------------+-------------------+
| 뉴서울(강남)      | 2,160             |
+-------------------+-------------------+
1 row in set (0.01 sec)</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Aggregate Functions(집계함수): Count, Sum, Avg, Min, Max / Group By, Having, CASE WHEN]]></title>
            <link>https://velog.io/@sss_yeonii/Aggregate-Functions%EC%A7%91%EA%B3%84%ED%95%A8%EC%88%98-Count-Sum-Avg-Min-Max-Group-By-Having</link>
            <guid>https://velog.io/@sss_yeonii/Aggregate-Functions%EC%A7%91%EA%B3%84%ED%95%A8%EC%88%98-Count-Sum-Avg-Min-Max-Group-By-Having</guid>
            <pubDate>Thu, 08 Aug 2024 11:43:31 GMT</pubDate>
            <description><![CDATA[<h1 id="aggregate-functions집계-함수">Aggregate Functions(집계 함수)</h1>
<ul>
<li>여러 컬럼 혹은 테이블 전체 컬럼으로부터 하나의 결과값을 반환하는 함수
<img src="https://velog.velcdn.com/images/sss_yeonii/post/370f7241-c957-4647-b476-48fc094d097a/image.png" alt=""></li>
</ul>
<h2 id="1-count">1. COUNT</h2>
<ul>
<li>총 갯수를 계산해주는 함수
```sql
// police_station 테이블의 데이터 총 개수
mysql&gt; select count(*) from police_station;</li>
<li>----------+
| count(*) |</li>
<li>----------+
|       31 |</li>
<li>----------+
1 row in set (0.02 sec)</li>
</ul>
<p>// crime_status 테이블에서 police_station 컬럼의 고유 값 개수 (경찰서는 총 몇 군데?)
mysql&gt; select count(distinct police_station) from crime_status;
+--------------------------------+
| count(distinct police_station) |
+--------------------------------+
|                             31 |
+--------------------------------+
1 row in set (0.07 sec)</p>
<p>// crime_type은 총 몇 가지? 
mysql&gt; select count(distinct crime_stype) from crime_status;
+-----------------------------+
| count(distinct crime_stype) |
+-----------------------------+
|                           6 |
+-----------------------------+
1 row in set (0.01 sec)</p>
<p>// 6개 있는 게 맞음.
mysql&gt; select distinct crime_stype from crime_status; 
+---------------+
| crime_stype    |
+---------------+
| 살인          |
| 강도          |
| 강간,추행     |
| 절도          |
| 폭력          |
| 강간          |
+---------------+
6 rows in set (0.02 sec)</p>
<p>// (컬럼명에 오타가 있길래 수정함..)
mysql&gt; alter table crime_status change crime_stype crime_type varchar(16);
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0</p>
<pre><code>## 2. SUM
```sql 
// 범죄 총 발생 건수
mysql&gt; select sum(case_number) from crime_status where status_type=&#39;발생&#39;;
+------------------+
| sum(case_number) |
+------------------+
|            92679 |
+------------------+
1 row in set (0.01 sec)

// 살인의 총 발생 건수
mysql&gt; select sum(case_number) from crime_status where crime_type=&#39;살인&#39; and status_type=&#39;발생&#39;;
+------------------+
| sum(case_number) |
+------------------+
|              141 |
+------------------+
1 row in set (0.04 sec)

// 중부경찰서에서 검거된 총 범죄 건수는?
mysql&gt; select sum(case_number) from crime_status where reference=&#39;서울중부경찰서&#39; and status_type=&#39;검거&#39; 
+------------------+
| sum(case_number) |
+------------------+
|             1406 |
+------------------+
1 row in set (0.01 sec)

// 1. police_station에서 경찰서는 총 몇 개이고, 각각 경찰서 이름은 무엇인지 확인하세요. 
mysql&gt; select count(distinct name) from police_station;
+----------------------+
| count(distinct name) |
+----------------------+
|                   31 |
+----------------------+
1 row in set (0.02 sec)
mysql&gt; select distinct name from police_station;
+--------------------------+
| name                     |
+--------------------------+
| 서울강남경찰서           |
| 서울강동경찰서           |
| 서울강북경찰서           |
| 서울강서경찰서           |
| 서울관악경찰서           |
| 서울광진경찰서           |
| 서울구로경찰서           |
| 서울금천경찰서           |
| 서울남대문경찰서         |
| 서울노원경찰서           |
| 서울도봉경찰서           |
| 서울동대문경찰서         |
| 서울동작경찰서           |
| 서울마포경찰서           |
| 서울방배경찰서           |
| 서울서대문경찰서         |
| 서울서부경찰서           |
| 서울서초경찰서           |
| 서울성동경찰서           |
| 서울성북경찰서           |
| 서울송파경찰서           |
| 서울수서경찰서           |
| 서울양천경찰서           |
| 서울영등포경찰서         |
| 서울용산경찰서           |
| 서울은평경찰서           |
| 서울종로경찰서           |
| 서울종암경찰서           |
| 서울중랑경찰서           |
| 서울중부경찰서           |
| 서울혜화경찰서           |
+--------------------------+
31 rows in set (0.01 sec)

// 2. crime_status에서 status_type은 총 몇 개이고, 각각 타입은 무엇인지 확인하세요. 
mysql&gt; select count(distinct status_type) from crime_status;
+-----------------------------+
| count(distinct status_type) |
+-----------------------------+
|                           2 |
+-----------------------------+
1 row in set (0.02 sec)

mysql&gt; select distinct status_type from crime_status;
+-------------+
| status_type |
+-------------+
| 발생        |
| 검거        |
+-------------+
2 rows in set (0.02 sec)

// 3. 종로경찰서와 남대문 경찰서의 강도 발생 건수의 합
mysql&gt; select sum(case_number)
    -&gt; from crime_status
    -&gt; where crime_type=&#39;강도&#39; and status_type=&#39;발생&#39; and police_station in (&#39;종로&#39;, &#39;남대문&#39;);
+------------------+
| sum(case_number) |
+------------------+
|                6 |
+------------------+
1 row in set (0.01 sec)


// 4. 폭력 범죄의 검거 건수의 합
mysql&gt; select sum(case_number)    
    -&gt; from crime_status
    -&gt; where crime_type=&#39;폭력&#39;
    -&gt; and status_type=&#39;검거&#39;;
+------------------+
| sum(case_number) |
+------------------+
|            41019 |
+------------------+
1 row in set (0.02 sec)</code></pre><h2 id="3-avg">3. Avg</h2>
<ul>
<li>숫자 컬럼의 평균을 계산
```sql
// 평균 폭력 검거 건수
mysql&gt; select AVG(case_number)
  -&gt; from crime_status
  -&gt; where crime_type like &#39;폭력&#39; and status_type=&#39;검거&#39;;</li>
<li>------------------+
| AVG(case_number) |</li>
<li>------------------+
|        1323.1935 |</li>
<li>------------------+
1 row in set (0.01 sec)</li>
</ul>
<p>// 중부경찰서 범죄 평균 발생 건수</p>
<p>mysql&gt; select AVG(case_number) from crime_status
    -&gt; where police_station like &#39;중부&#39; and status_type=&#39;발생&#39;;
+------------------+
| AVG(case_number) |
+------------------+
|         411.4000 |
+------------------+
1 row in set (0.02 sec)</p>
<pre><code>## 4. MIN/MAX
- MIN: 숫자 컬럼 중 가장 작은 값을 찾아주는 함수
- MAX: 숫자 컬럼 중 가장 큰 값을 찾아주는 함수
select min(case_number) from crime_status
```sql
//1. 강도 발생 건수가 가장 적은 경우는 몇 건?
mysql&gt; select min(case_number) from crime_status
    -&gt; where status_type=&#39;발생&#39; and crime_type=&#39;강도&#39;;
+------------------+
| min(case_number) |
+------------------+
|                1 |
+------------------+
1 row in set (0.01 sec)

// 2. 중부경찰서에서 가장 낮은 검거 건수는?
mysql&gt; select min(case_number) from crime_status
    -&gt; where status_type=&#39;검거&#39; and police_station like &#39;중부&#39;;
+------------------+
| min(case_number) |
+------------------+
|                1 |
+------------------+
1 row in set (0.02 sec)

// 3. 살인이 가장 많이 검거된 건수는?
mysql&gt; select max(case_number) from crime_status
    -&gt; where crime_type=&#39;살인&#39; and status_type=&#39;검거&#39;;
+------------------+
| max(case_number) |
+------------------+
|               12 |
+------------------+
1 row in set (0.03 sec)


// 4. 강남 경찰서에서 가장 많이 발생한 범죄 건수는?
mysql&gt; select max(case_number) from crime_status
    -&gt; where police_station like &#39;강남&#39; and status_type=&#39;발생&#39;;
+------------------+
| max(case_number) |
+------------------+
|             2283 |
+------------------+
1 row in set (0.02 sec)

// 5. 성북경찰서에서 가장 낮은 범죄 발생 건수는? -&gt; 살인이 0건
mysql&gt; select min(case_number) from crime_status
    -&gt; where police_station like &#39;성북&#39; and status_type=&#39;발생&#39;;
+------------------+
| min(case_number) |
+------------------+
|                0 |
+------------------+
1 row in set (0.10 sec)

mysql&gt; select * from crime_status
    -&gt; where police_station like &#39;성북&#39; and status_type=&#39;발생&#39;;
+------+----------------+------------+-------------+-------------+-----------------------+
| year | police_station | crime_type | status_type | case_number | reference             |
+------+----------------+------------+-------------+-------------+-----------------------+
| 2020 | 성북           | 살인       | 발생        |           0 | 서울성북경찰서        |
| 2020 | 성북           | 강도       | 발생        |           2 | 서울성북경찰서        |
| 2020 | 성북           | 강간       | 발생        |          95 | 서울성북경찰서        |
| 2020 | 성북           | 절도       | 발생        |         439 | 서울성북경찰서        |
| 2020 | 성북           | 폭력       | 발생        |         672 | 서울성북경찰서        |
+------+----------------+------------+-------------+-------------+-----------------------+
5 rows in set (0.01 sec)</code></pre><h2 id="5-group-by">5. GROUP BY</h2>
<ul>
<li>그룹화하여 데이터를 조회</li>
<li>단, DISTINCT 사용하는 경우 ORDER BY 사용할 수 없음.<pre><code class="language-sql">SELECT col1, col2, ...
FROM tablename
WHERE condition
GROUP BY col1, col2, ...
ORDER BY col1, col2, ...
</code></pre>
</li>
</ul>
<p>// 경찰서 종류별 건수 검색</p>
<pre><code class="language-sql">mysql&gt; SELECT police_station, sum(case_number) 
       FROM crime_status 
       GROUP BY police_station 
       ORDER BY sum(case_number);
+----------------+------------------+
| police_station | sum(case_number) |
+----------------+------------------+
| 방배           |             1412 |
| 성북           |             2130 |
| 남대문         |             2271 |
| 종암           |             2384 |
| 혜화           |             2402 |
| 서부           |             2427 |
| 종로           |             2873 |
| 중부           |             3463 |
| 은평           |             3494 |
| 도봉           |             3669 |
| 성동           |             4136 |
| 서대문         |             4239 |
| 수서           |             4474 |
| 금천           |             4564 |
| 용산           |             5025 |
| 강북           |             5029 |
| 동작           |             5286 |
| 양천           |             5302 |
| 동대문         |             5866 |
| 광진           |             6112 |
| 마포           |             6222 |
| 서초           |             6241 |
| 노원           |             6324 |
| 강동           |             6450 |
| 중랑           |             6507 |
| 구로           |             7159 |
| 강서           |             7808 |
| 강남           |             8127 |
| 영등포         |             8588 |
| 송파           |             8954 |
| 관악           |             9119 |
+----------------+------------------+
31 rows in set (0.01 sec)


// 경찰서 종류 검색: 
SELECT DISTINCT police_station
FROM crime_status


// 경찰서별 총 발생 범죄 건수 검색
mysql&gt; select police_station, sum(case_number) 발생건수
    -&gt; from crime_status
    -&gt; where status_type = &#39;발생&#39; 
    -&gt; group by police_station
    -&gt; order by 발생건수 DESC;
+----------------+--------------+
| police_station | 발생건수     |
+----------------+--------------+
| 송파           |         5410 |
| 관악           |         5261 |
| 영등포         |         5217 |
| 강남           |         4754 |
| 강서           |         4415 |
| 구로           |         4175 |
| 강동           |         3788 |
| 서초           |         3765 |
| 노원           |         3743 |
| 중랑           |         3726 |
| 마포           |         3688 |
| 광진           |         3601 |
| 동대문         |         3401 |
| 양천           |         3216 |
| 동작           |         3200 |
| 용산           |         2969 |
| 강북           |         2770 |
| 수서           |         2602 |
| 금천           |         2598 |
| 서대문         |         2533 |
| 성동           |         2362 |
| 도봉           |         2179 |
| 중부           |         2057 |
| 은평           |         2028 |
| 종로           |         1694 |
| 혜화           |         1408 |
| 서부           |         1362 |
| 종암           |         1359 |
| 남대문         |         1354 |
| 성북           |         1208 |
| 방배           |          836 |
+----------------+--------------+
31 rows in set (0.02 sec)

// 경찰서별 평균 범죄 발생건수와 평균 범죄 검거건수를 검색
mysql&gt; select police_station 경찰서, status_type, avg(case_number)
    -&gt; from crime_status
    -&gt; group by police_station, status_type
    -&gt; limit 8;
+-----------+-------------+------------------+
| 경찰서    | status_type | avg(case_number) |
+-----------+-------------+------------------+
| 중부      | 발생        |         411.4000 |
| 중부      | 검거        |         281.2000 |
| 종로      | 발생        |         338.8000 |
| 종로      | 검거        |         235.8000 |
| 남대문    | 발생        |         270.8000 |
| 남대문    | 검거        |         183.4000 |
| 서대문    | 발생        |         506.6000 |
| 서대문    | 검거        |         341.2000 |
+-----------+-------------+------------------+
8 rows in set (0.01 sec)</code></pre>
<h2 id="6-having">6. HAVING</h2>
<ul>
<li>항상 Group by 뒤에 위치하며, Group by 된 이후 특정 필드로 그룹화된 새로운 테이블에 조건을 주는 것. </li>
<li><strong>WHERE과 차이점</strong><ul>
<li>전체 테이블 자체에서 조건을 걸고 싶으면 WHERE을, </li>
<li>전체 테이블을 그룹화한 후 조건을 걸고 싶으면 HAVING을 사용함.</li>
<li>집계함수(COUNT, MIN, MAX, SUM, AVG 등)는 HAVING과만 사용할 수 있다.</li>
</ul>
</li>
<li>Having까지 적용해서 만든 테이블을 정렬하는 것이기 때문에 <code>Group by -&gt; Having -&gt; Order by</code> 순서로 작성해야 함 주의!<pre><code class="language-sql">// 경찰서별로 발생한 범죄 검수의 합이 4000건 보다 큰 경우를 검색
select police_station 경찰서, sum(case_number) 범죄발생건수
from crime_status
where status_type like &#39;발생&#39;
group by police_station
having 범죄발생건수 &gt; 4000;
</code></pre>
</li>
</ul>
<p>+-----------+--------------------+
| 경찰서    | 범죄발생건수       |
+-----------+--------------------+
| 영등포    |               5217 |
| 강남      |               4754 |
| 관악      |               5261 |
| 강서      |               4415 |
| 구로      |               4175 |
| 송파      |               5410 |
+-----------+--------------------+
6 rows in set (0.13 sec)</p>
<p>// 경찰서별로 발생한 폭력과 절도의 범죄 건수 평균이 2000 이상인 경우를 검색
mysql&gt; select police_station 경찰서, avg(case_number)
    -&gt; from crime_status
    -&gt; where status_type like &#39;발생&#39; 
    -&gt; and crime_type in (&#39;폭력&#39;, &#39;절도&#39;)
    -&gt; group by police_station
    -&gt; having avg(case_number) &gt;= 2000;
+-----------+------------------+
| 경찰서    | avg(case_number) |
+-----------+------------------+
| 영등포    |        2444.5000 |
| 강남      |        2112.0000 |
| 관악      |        2421.5000 |
| 강서      |        2067.0000 |
| 송파      |        2552.0000 |
+-----------+------------------+
5 rows in set (0.03 sec)</p>
<p>//경찰서별로 절도 범죄 평균 발생 건수를 가장 많은 건수 순으로 10개 검색하고 확인하세요.
mysql&gt; select police_station 경찰서, avg(case_number) 절도범죄평균발생건수
    -&gt; from crime_status
    -&gt; where status_type like &#39;발생&#39; 
    -&gt; and crime_type like &#39;절도&#39;
    -&gt; group by police_station
    -&gt; order by 절도범죄평균발생건수 DESC
    -&gt; limit 10;
+-----------+--------------------------------+
| 경찰서    | 절도범죄평균발생건수           |
+-----------+--------------------------------+
| 송파      |                      2429.0000 |
| 관악      |                      2229.0000 |
| 영등포    |                      2188.0000 |
| 강남      |                      1941.0000 |
| 구로      |                      1763.0000 |
| 강서      |                      1689.0000 |
| 서초      |                      1673.0000 |
| 광진      |                      1664.0000 |
| 강동      |                      1640.0000 |
| 양천      |                      1517.0000 |
+-----------+--------------------------------+
10 rows in set (0.01 sec)</p>
<p>// 경찰서별로 가장 많이 검거한 범죄 건수를 가장 적은 건수 순으로 5개 검색하세요.
mysql&gt; select police_station 경찰서, max(case_number)
    -&gt; from crime_status
    -&gt; where status_type like &#39;검거&#39;
    -&gt; group by police_station
    -&gt; order by max(case_number)
    -&gt; limit 5;
+-----------+------------------+
| 경찰서    | max(case_number) |
+-----------+------------------+
| 방배      |              365 |
| 남대문    |              494 |
| 성북      |              610 |
| 혜화      |              628 |
| 종암      |              630 |
+-----------+------------------+
5 rows in set (0.02 sec)</p>
<p>// 경찰서별로 가장 적게 검거한 건수 중 4건보다 큰 경우를 건수가 큰 순으로 정렬하여 검색하세요. 
mysql&gt; select police_station 경찰서, min(case_number)
    -&gt; from crime_status
    -&gt; where status_type like &#39;검거&#39;
    -&gt; group by police_station
    -&gt; having min(case_number) &gt; 4
    -&gt; order by min(case_number) desc;
+-----------+------------------+
| 경찰서    | min(case_number) |
+-----------+------------------+
| 중랑      |                6 |
| 송파      |                6 |
| 동대문    |                5 |
| 강서      |                5 |
| 구로      |                5 |
+-----------+------------------+
5 rows in set (0.01 sec)</p>
<p>// &#39;대문&#39;으로 끝나는 이름의 경찰서별 범죄발생 건수의 평균이 500건 이상인 경우를 검색하세요. 
mysql&gt; select police_station 경찰서, avg(case_number) 평균범죄발생건수
    -&gt; from crime_status
    -&gt; where status_type like &#39;발생&#39; and police_station like &#39;%대문&#39;
    -&gt; group by police_station
    -&gt; having 평균범죄발생건수 &gt;= 500;
+-----------+--------------------------+
| 경찰서    | 평균범죄발생건수         |
+-----------+--------------------------+
| 서대문    |                 506.6000 |
| 동대문    |                 680.2000 |
+-----------+--------------------------+
2 rows in set (0.01 sec)</p>
<pre><code>
## 7. Case, When
- 기존의 열과 조건문을 이용해서 새로운 열을 만들고 싶을 때</code></pre><p>SELECT CASE
           WHEN 조건 1 THEN &#39;이름1&#39;
        WHEN 조건 1 THEN &#39;이름1&#39;
        WHEN 조건 1 THEN &#39;이름1&#39;
        ELSE &#39;이름4&#39; END AS 새로운 열 이름</p>
<pre><code>- 조건문은 순차적으로 진행한다. 첫번째 조건을 만족하면 다음 조건은 확인하지 않고 바로 첫번째 조건의 이름을 부여한다. 
- 마지막 ELSE는 생략 가능하다. 만약 ELSE 설정을 안했다면, ELSE에 해당하는 값에 null이 생김.
- END는 꼭 붙여줘야 한다.</code></pre><p>SELECT OrderID, Quantity,
  CASE 
      WHEN Quantity &gt; 30 THEN &#39;The quantity is greater than 30&#39;
      WHEN Quantity = 30 THEN &#39;The quantity is 30&#39;
      ELSE &#39;The quantity is under 30&#39;
      END AS QuantityText
  FROM OrderDetails;</p>
<pre><code></code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[MySQL] Primary Key(기본키), Foreign Key(외래키)]]></title>
            <link>https://velog.io/@sss_yeonii/MySQL-Primary-Key%EA%B8%B0%EB%B3%B8%ED%82%A4-Foreign-Key%EC%99%B8%EB%9E%98%ED%82%A4</link>
            <guid>https://velog.io/@sss_yeonii/MySQL-Primary-Key%EA%B8%B0%EB%B3%B8%ED%82%A4-Foreign-Key%EC%99%B8%EB%9E%98%ED%82%A4</guid>
            <pubDate>Thu, 08 Aug 2024 08:44:29 GMT</pubDate>
            <description><![CDATA[<h1 id="primary-key">Primary Key</h1>
<h2 id="primary-key기본-키란">PRIMARY KEY(기본 키)란?</h2>
<ul>
<li>테이블의 각 레코드를 식별</li>
<li>중복되지 않은 고유값을 포함</li>
<li>Null값을 포함할 수 없음</li>
<li>테이블당 하나의 기본 키를 가짐</li>
<li>기본 키는 컬럼 하나로 지정할 수도 있고, 여러 컬럼을 하나의 기본 키로 설정할 수도 있음. <h2 id="1-테이블-생성-시-primary-key-지정하는-문법">1) 테이블 생성 시 PRIMARY KEY 지정하는 문법</h2>
<pre><code class="language-sql">CREATE TABLE tablename
(
  column1 datatype NOT NULL,
  column2 datatype NOT NULL,
  ...
  CONSTRAINT constraint_name  #생략도 가능함
      PRIMARY KEY (column1, column2, ...)
);</code></pre>
<h3 id="하나의-컬럼을-기본-키로-설정하는-경우">하나의 컬럼을 기본 키로 설정하는 경우</h3>
<pre><code class="language-sql">CREATE TABLE person
(
  pid int NOT NULL,
  name varchar(16),
  age int,
  sex char,
  PRIMARY KEY (pid)
);
</code></pre>
</li>
</ul>
<p>...</p>
<h1 id="pid의-key에-pri로-primary-key-지정된-것-확인할-수-있음">pid의 Key에 PRI로 Primary Key 지정된 것 확인할 수 있음.</h1>
<p>mysql&gt; desc person;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| pid   | int         | NO   | PRI | NULL    |       |
| name  | varchar(16) | YES  |     | NULL    |       |
| age   | int         | YES  |     | NULL    |       |
| sex   | char(1)     | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.01 sec)</p>
<pre><code>### 여러 개의 컬럼을 기본 키로 설정하는 경우
```sql
CREATE TABLE animal
(
    name varchar(16) NOT NULL,
    type varchar(16) NOT NULL,
    age int,
    PRIMARY KEY (name, type)
);

...
mysql&gt; desc animal;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| name  | varchar(16) | NO   | PRI | NULL    |       |
| type  | varchar(16) | NO   | PRI | NULL    |       |
| age   | int         | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.07 sec)</code></pre><h2 id="2-primary-key-삭제하는-문법">2) PRIMARY KEY 삭제하는 문법</h2>
<p>테이블당 Primary key는 하나이기 때문에 별도로 컬럼명을 쓰지 않아도 tablename의 Primary key가 삭제됨</p>
<pre><code class="language-sql">ALTER TABLE tablename
DROP PRIMARY KEY;</code></pre>
<h2 id="3-이미-만들어진-테이블에-primary-key-추가하는-문법">3) 이미 만들어진 테이블에 PRIMARY KEY 추가하는 문법</h2>
<pre><code class="language-sql">ALTER TABLE tablename
ADD PRIMARY KEY (col1, col2, ...);</code></pre>
<h3 id="하나의-컬럼을-기본-키로-설정하는-경우-1">하나의 컬럼을 기본 키로 설정하는 경우</h3>
<pre><code class="language-sql">ALTER TABLE person
ADD PRIMARY KEY (pid);</code></pre>
<h3 id="여러-컬럼을-기본-키로-설정하는-경우">여러 컬럼을 기본 키로 설정하는 경우</h3>
<pre><code class="language-sql">ALTER TABLE animal
ADD CONSTRAINT PK_animal  #(생략 가능)animal 테이블에 PK(primary key) 지정하겠다는 뜻
ADD PRIMARY KEY (name, type);</code></pre>
<h1 id="foreign-key-외래키">Foreign Key (외래키)</h1>
<h2 id="foreign-key-외래키란">Foreign Key (외래키)란?</h2>
<ul>
<li>한 테이블을 다른 테이블과 연결해주는 역할이며, 참조되는 테이블의 항목은 그 테이블의 기본키(Primary Key) 혹은 단일값이어야 함.</li>
<li>Foreign Key는 두 테이블을 JOIN 시킬 때 활용<h3 id="1-create-table에서-foreign-key를-지정하는-경우-문법">1) Create Table에서 Foreign Key를 지정하는 경우 문법</h3>
<pre><code class="language-sql">CREATE TABLE tablename
(
  column1 datatype NOT NULL,
  column2 datatype NOT NULL,
  ...
  CONSTRAINT constraint_name  (생략 가능)
      PRIMARY KEY (column1, column2, ...),
  CONSTRAINT constraint_name  (생략 가능)
      FOREIGN KEY (column1, column2, ...) REFERENCES REF_tablename(REF_column)
      // REFERENCES: 어떤 테이블의 어떤 컬럼을 참조할 것인지
);</code></pre>
</li>
<li>Create Table에서 Foreign Key를 지정하는 경우, REFERENCES에서 어떤 테이블의 컬럼을 참조할지 지정</li>
<li>Foreign Key는 다른 테이블의 항목을 참조하기 때문에 여러개가 존재할 수 있음. <h4 id="1-1-실습-예제">1-1) 실습 예제</h4>
<pre><code class="language-sql">CREATE TABLE orders
(
  oid int not null,
  order_no varchar(16),
  pid int,    
  primary key (oid),
  CONSTRAINT FK_person FOREIGN KEY (pid) REFERENCES person(pid)
);
</code></pre>
</li>
</ul>
<p>mysql&gt; desc orders;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| oid      | int         | NO   | PRI | NULL    |       |
| order_no | varchar(16) | YES  |     | NULL    |       |
| pid      | int         | YES  | MUL | NULL    |       |
+----------+-------------+------+-----+---------+-------+
3 rows in set (0.02 sec)</p>
<p>// oid: Primary Key로 지정
// pid: Foreign Key로 지정</p>
<pre><code>#### 1-2) CONSTRAINT 생략하여 Foreign Key 생성
- `show create table tablename;`: Constaraint 이름 알 수 있음
=&gt; 자동 생성된 CONSTRAINT인 `job_ibfk_1`을 확인할 수 있음.
```sql
mysql&gt; CREATE TABLE job
    -&gt; (
    -&gt;        jid int not null,
    -&gt;     name varchar(16),
    -&gt;     pid int,    
    -&gt;     primary key (jid),
    -&gt;     FOREIGN KEY (pid) REFERENCES person(pid)
    -&gt; );
Query OK, 0 rows affected (0.05 sec)

mysql&gt; desc job;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| jid   | int         | NO   | PRI | NULL    |       |
| name  | varchar(16) | YES  |     | NULL    |       |
| pid   | int         | YES  | MUL | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)

mysql&gt; show create table job;
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                                                                     |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| job   | CREATE TABLE `job` (
  `jid` int NOT NULL,
  `name` varchar(16) DEFAULT NULL,
  `pid` int DEFAULT NULL,
  PRIMARY KEY (`jid`),
  KEY `pid` (`pid`),
  CONSTRAINT `job_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `person` (`pid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.02 sec)</code></pre><h3 id="2-foreign-key-삭제-문법">2) Foreign Key 삭제 문법</h3>
<p><code>alter table tablename /
drop foreign key FK_constraint_name;</code>
=&gt; desc tablename하면, Key 컬럼에 MUL이라고 FK 설정이 남아있는 것처럼 보이지만.. 
=&gt; show create table tablename을 하면, CONSTRAINT 없이 KEY 속성만 남아있는 것을 볼 수 있음.</p>
<pre><code class="language-sql">mysql&gt; alter table orders
    -&gt; drop foreign key FK_person;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql&gt; desc orders;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| oid      | int         | NO   | PRI | NULL    |       |
| order_no | varchar(16) | YES  |     | NULL    |       |
| pid      | int         | YES  | MUL | NULL    |       |
+----------+-------------+------+-----+---------+-------+
3 rows in set (0.02 sec)

mysql&gt; show create table orders;
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table  | Create Table                                                                                                                                                                                                                       |
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| orders | CREATE TABLE `orders` (
  `oid` int NOT NULL,
  `order_no` varchar(16) DEFAULT NULL,
  `pid` int DEFAULT NULL,
  PRIMARY KEY (`oid`),
  KEY `FK_person` (`pid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.03 sec)</code></pre>
<h3 id="3-이미-생성된-테이블에-foreign-key-추가">3) 이미 생성된 테이블에 Foreign Key 추가</h3>
<pre><code class="language-sql">ALTER TABLE tablename
ADD FOREIGN KEY (column) REFERENCES REF_tablename(REF_column);</code></pre>
<ul>
<li>table이 생성된 이후 ALTER TABLE로 FK를 추가할 수 있음.<h4 id="실습-예제">&lt;실습 예제&gt;</h4>
<pre><code class="language-sql">mysql&gt; alter table orders
  -&gt; add foreign key (pid) references person(pid);
Query OK, 0 rows affected (0.10 sec)
Records: 0  Duplicates: 0  Warnings: 0
</code></pre>
</li>
</ul>
<p>mysql&gt; show create table orders;
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table  | Create Table                                                                                                                                                                                                                                                                                               |
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| orders | CREATE TABLE <code>orders</code> (
  <code>oid</code> int NOT NULL,
  <code>order_no</code> varchar(16) DEFAULT NULL,
  <code>pid</code> int DEFAULT NULL,
  PRIMARY KEY (<code>oid</code>),
  KEY <code>pid</code> (<code>pid</code>),
  CONSTRAINT <code>orders_ibfk_1</code> FOREIGN KEY (<code>pid</code>) REFERENCES <code>person</code> (<code>pid</code>)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)</p>
<p>// 자동으로 FK orders_ibfk_1가 지정되어 생성된 것을 확인할 수 있음. </p>
<pre><code>### 실습 예제) police_station과 crime_status 테이블 사이에 관계(Foreign Key)를 설정해보기
```sql
// police_station.name과 crime_status.police_station 을 매칭시켜 관계를 맺도록 할 예정!
// 1. 각 컬럼의 고유값 개수가 일치하는지 확인해보자. 

mysql&gt; select count(distinct name) from police_station;
+----------------------+
| count(distinct name) |
+----------------------+
|                   31 |
+----------------------+
1 row in set (0.02 sec)

mysql&gt; select count(distinct police_station) from crime_status;
+--------------------------------+
| count(distinct police_station) |
+--------------------------------+
|                             31 |
+--------------------------------+
1 row in set (0.01 sec)

// 2. 경찰서 이름이 각 테이블에서 표시되는 형식이 다르다.
mysql&gt; select distinct name from police_station limit 3;
+--------------------------+
| name                     |
+--------------------------+
| 서울중부경찰서           |
| 서울종로경찰서           |
| 서울남대문경찰서         |
+--------------------------+
3 rows in set (0.02 sec)

mysql&gt; select distinct police_station from crime_status limit 3;
+----------------+
| police_station |
+----------------+
| 중부           |
| 종로           |
| 남대문         |
+----------------+
3 rows in set (0.02 sec)

// 3. &#39;서울&#39;+crime_status.police_station+&#39;경찰서&#39; 의 값이 police_station.name과 일치할지 비교해보자. =&gt; 31개로 모두 일치

select c.police_station, p.name
from crime_status c, police_station p
where p.name like concat(&#39;서울&#39;, c.police_station, &#39;경찰서&#39;)
group by c.police_station, p.name;

mysql&gt; select c.police_station, p.name
    -&gt; from crime_status c, police_station p
    -&gt; where p.name like concat(&#39;서울&#39;, c.police_station, &#39;경찰서&#39;) 
    -&gt; group by c.police_station, p.name;
+----------------+--------------------------+
| police_station | name                     |
+----------------+--------------------------+
| 중부           | 서울중부경찰서           |
| 종로           | 서울종로경찰서           |
| 남대문         | 서울남대문경찰서         |
| 서대문         | 서울서대문경찰서         |
| 혜화           | 서울혜화경찰서           |
| 용산           | 서울용산경찰서           |
| 성북           | 서울성북경찰서           |
| 동대문         | 서울동대문경찰서         |
| 마포           | 서울마포경찰서           |
| 영등포         | 서울영등포경찰서         |
| 성동           | 서울성동경찰서           |
| 동작           | 서울동작경찰서           |
| 광진           | 서울광진경찰서           |
| 서부           | 서울서부경찰서           |
| 강북           | 서울강북경찰서           |
| 금천           | 서울금천경찰서           |
| 중랑           | 서울중랑경찰서           |
| 강남           | 서울강남경찰서           |
| 관악           | 서울관악경찰서           |
| 강서           | 서울강서경찰서           |
| 강동           | 서울강동경찰서           |
| 종암           | 서울종암경찰서           |
| 구로           | 서울구로경찰서           |
| 서초           | 서울서초경찰서           |
| 양천           | 서울양천경찰서           |
| 송파           | 서울송파경찰서           |
| 노원           | 서울노원경찰서           |
| 방배           | 서울방배경찰서           |
| 은평           | 서울은평경찰서           |
| 도봉           | 서울도봉경찰서           |
| 수서           | 서울수서경찰서           |
+----------------+--------------------------+
31 rows in set (0.03 sec)

//4. 참조할 police_station.name을 Primary Key로 설정 

ALTER TABLE police_station
ADD PRIMARY KEY (name);

mysql&gt; desc police_station;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| name    | varchar(16)  | NO   | PRI | NULL    |       |
| address | varchar(128) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
2 rows in set (0.02 sec)


// 5. crime_status 테이블에 Foreign Key로 사용할 reference 컬럼 추가  =&gt; 비어있는 값으로 생성됨
ALTER TABLE crime_status
ADD COLUMN reference VARCHAR(16);

// 6. reference 컬럼으로 Foreign Key 생성
ALTER TABLE crime_status
ADD FOREIGN KEY (reference) REFERENCES police_station(name);

mysql&gt; desc crime_status;
+----------------+-------------+------+-----+---------+-------+
| Field          | Type        | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+-------+
| year           | year        | YES  |     | NULL    |       |
| police_station | varchar(8)  | YES  |     | NULL    |       |
| crime_stype    | varchar(16) | YES  |     | NULL    |       |
| status_type    | char(2)     | YES  |     | NULL    |       |
| case_number    | int         | YES  |     | NULL    |       |
| reference      | varchar(16) | YES  | MUL | NULL    |       |
+----------------+-------------+------+-----+---------+-------+
6 rows in set (0.02 sec)

// 7. reference 컬럼에 값 채워주기
UPDATE crime_status c, police_station p
SET c.reference = p.name
WHERE p.name LIKE concat(&#39;서울&#39;, c.police_station, &#39;경찰서&#39;);

mysql&gt; select distinct reference from crime_status limit 5;
+-----------------------+
| reference             |
+-----------------------+
| 서울강남경찰서        |
| 서울강동경찰서        |
| 서울강북경찰서        |
| 서울강서경찰서        |
| 서울관악경찰서        |
+-----------------------+
5 rows in set (0.01 sec)

// 8. 이제 Foreign Key인 reference 컬럼을 기준으로 두 테이블을 연관시켜 검색할 수 있다. 
SELECT c.police_station, p.address 
FROM crime_status c, police_station p
WHERE c.reference = p.name
GROUP BY c.police_station;
+----------------+----------------------------------------------------------------------------------+
| police_station | address                                                                          |
+----------------+----------------------------------------------------------------------------------+
| 중부           | 서울특별시 중구 수표로 27                                                        |
| 종로           | 서울특별시 종로구 율곡로 46                                                      |
| 남대문         | 서울특별시 중구 한강대로 410                                                     |
| 서대문         | 서울특별시 서대문구 통일로 113                                                   |
| 혜화           | 서울특별시 종로구 창경궁로 112-16                                                |
| 용산           | 서울특별시 용산구 원효로89길 24                                                  |
| 성북           | 서울특별시 성북구 보문로 170                                                     |
| 동대문         | 서울특별시 동대문구 약령시로 21길 29                                             |
| 마포           | 서울특별시 마포구 마포대로 183                                                   |
| 영등포         | 서울특별시 영등포구 국회대로 608                                                 |
| 성동           | 서울특별시 성동구 왕십리광장로 9                                                 |
| 동작           | 서울특별시 동작구 노량진로 148                                                   |
| 광진           | 서울특별시 광진구 광나루로 447 광진소방서 임시청사 (능동)                        |
| 서부           | 서울특별시 은평구 은평로9길 15                                                   |
| 강북           | 서울특별시 강북구 오패산로 406                                                   |
| 금천           | 서울특별시 관악구 남부순환로 1435                                                |
| 중랑           | 서울특별시 중랑구 중랑역로 137                                                   |
| 강남           | 서울특별시 강남구 테헤란로 114길 11                                              |
| 관악           | 서울특별시 관악구 관악로5길 33                                                   |
| 강서           | 서울특별시 양천구 화곡로 73                                                      |
| 강동           | 서울특별시 강동구 성내로 33                                                      |
| 종암           | 서울특별시 성북구 종암로 135                                                     |
| 구로           | 서울특별시 구로구 가마산로 235                                                   |
| 서초           | 서울특별시 서초구 반포대로 179                                                   |
| 양천           | 서울특별시 양천구 목동동로 99                                                    |
| 송파           | 서울특별시 송파구 중대로 221                                                     |
| 노원           | 서울특별시 노원구 노원로 283                                                     |
| 방배           | 서울특별시 서초구 방배천로 54                                                    |
| 은평           | 서울특별시 은평구 연서로 365                                                     |
| 도봉           | 서울특별시 도봉구 노해로 403                                                     |
| 수서           | 서울특별시 강남구 개포로 617                                                     |
+----------------+----------------------------------------------------------------------------------+
31 rows in set (0.01 sec)</code></pre><hr>
<h4 id="혼자서-해보기-실습">혼자서 해보기 실습:</h4>
<pre><code class="language-sql">// 1. study 테이블 생성 (PK: study_id, FK: patient_id (person의 pid 참조)

mysql&gt; CREATE TABLE study(
    -&gt; study_id int not null,
    -&gt; study_date date,
    -&gt; study_time time,
    -&gt; patient_id int,
    -&gt; PRIMARY KEY (study_id),
    -&gt; FOREIGN KEY (patient_id) REFERENCES person(pid)
    -&gt; );
Query OK, 0 rows affected (0.04 sec)

mysql&gt; desc study;
+------------+------+------+-----+---------+-------+
| Field      | Type | Null | Key | Default | Extra |
+------------+------+------+-----+---------+-------+
| study_id   | int  | NO   | PRI | NULL    |       |
| study_date | date | YES  |     | NULL    |       |
| study_time | time | YES  |     | NULL    |       |
| patient_id | int  | YES  | MUL | NULL    |       |
+------------+------+------+-----+---------+-------+
4 rows in set (0.01 sec)

// 2. primary key, foreign key 삭제
mysql&gt; alter table study
    -&gt; drop primary key;
Query OK, 0 rows affected (0.08 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql&gt; show create table study;
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                                                                                                                    |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| study | CREATE TABLE `study` (
  `study_id` int NOT NULL,
  `study_date` date DEFAULT NULL,
  `study_time` time DEFAULT NULL,
  `patient_id` int DEFAULT NULL,
  KEY `patient_id` (`patient_id`),
  CONSTRAINT `study_ibfk_1` FOREIGN KEY (`patient_id`) REFERENCES `person` (`pid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

mysql&gt; alter table study
    -&gt; drop foreign key study_ibfk_1;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql&gt; desc study;
+------------+------+------+-----+---------+-------+
| Field      | Type | Null | Key | Default | Extra |
+------------+------+------+-----+---------+-------+
| study_id   | int  | NO   |     | NULL    |       |
| study_date | date | YES  |     | NULL    |       |
| study_time | time | YES  |     | NULL    |       |
| patient_id | int  | YES  | MUL | NULL    |       |
+------------+------+------+-----+---------+-------+
4 rows in set (0.01 sec)

// 3. FK: patient_id, PK: study_id 등록하기
mysql&gt; alter table study
    -&gt; add foreign key (patient_id) references person(pid);
Query OK, 0 rows affected (0.07 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql&gt; alter table study
    -&gt; add primary key (study_id);
Query OK, 0 rows affected (0.06 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql&gt; show create table study;
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                                                                                                                                                |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| study | CREATE TABLE `study` (
  `study_id` int NOT NULL,
  `study_date` date DEFAULT NULL,
  `study_time` time DEFAULT NULL,
  `patient_id` int DEFAULT NULL,
  PRIMARY KEY (`study_id`),
  KEY `patient_id` (`patient_id`),
  CONSTRAINT `study_ibfk_1` FOREIGN KEY (`patient_id`) REFERENCES `person` (`pid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

mysql&gt; desc study;
+------------+------+------+-----+---------+-------+
| Field      | Type | Null | Key | Default | Extra |
+------------+------+------+-----+---------+-------+
| study_id   | int  | NO   | PRI | NULL    |       |
| study_date | date | YES  |     | NULL    |       |
| study_time | time | YES  |     | NULL    |       |
| patient_id | int  | YES  | MUL | NULL    |       |
+------------+------+------+-----+---------+-------+
4 rows in set (0.01 sec)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[파이썬에서 MySQL 실행하기]]></title>
            <link>https://velog.io/@sss_yeonii/%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%97%90%EC%84%9C-MySQL-%EC%8B%A4%ED%96%89%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sss_yeonii/%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%97%90%EC%84%9C-MySQL-%EC%8B%A4%ED%96%89%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 30 Jul 2024 15:13:57 GMT</pubDate>
            <description><![CDATA[<h1 id="파이썬에서-mysql-실행하기">파이썬에서 MySQL 실행하기</h1>
<h4 id="실습-환경-만들기-police_station-백업-파일-만들어놓기">실습 환경 만들기: police_station 백업 파일 만들어놓기</h4>
<pre><code class="language-sql"># zerobase 데이터베이스의 police_station 테이블을 backup_police.sql로 백업
mysqldump --set-gtid-purged=OFF -h &quot;database-1.cpys04aeky7e.ap-northeast-2.rds.amazonaws.com&quot; -P 3306 -u admin -p zerobase police_station &gt; backup_police.sql

# 내 AWS RDS 접속
mysqldump -h &quot;database-1.cpys04aeky7e.ap-northeast-2.rds.amazonaws.com&quot; -P 3306 -u admin -p zerobase

mysql&gt; show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| zerobase           |
+--------------------+
5 rows in set (0.01 sec)

# zerobase 데이터베이스 선택
mysql&gt; use zerobase

mysql&gt; show tables;
+--------------------+
| Tables_in_zerobase |
+--------------------+
| celeb              |
| crime_status       |
| police_station     |
| snl_show           |
+--------------------+
4 rows in set (0.01 sec)

# 저장되어있는 police_station의 데이터 삭제
mysql&gt; delete from police_station;
Query OK, 0 rows affected (0.06 sec)

mysql&gt; show tables;
+--------------------+
| Tables_in_zerobase |
+--------------------+
| celeb              |
| crime_status       |
| police_station     |
| snl_show           |
+--------------------+
4 rows in set (0.01 sec)

mysql&gt; select * from police_station;
Empty set (0.01 sec) </code></pre>
<h2 id="1-python에서-mysql을-사용하기-위해-mysql-driver-설치">1. Python에서 MySQL을 사용하기 위해 MySQL Driver 설치</h2>
<pre><code class="language-python">pip install mysql-connector-python
import mysql.connector</code></pre>
<ul>
<li>MySQLCursor.execute() 공식문서: <a href="https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html">https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html</a><h2 id="2-mysqlconnector-사용하여-데이터베이스-연결하기">2. mysql.connector 사용하여 데이터베이스 연결하기</h2>
<pre><code class="language-python">#Local Database 연결
mydb = mysql.connector.connect(
  host = &quot;localhost&quot;,
  user = &quot;root&quot;,
  password = &quot;&lt;password&gt;&quot;
  #데이터베이스 지정해서 접근하려면, database=&quot;&lt;databasename&gt;&quot;
)
# 종료 필수! 연결이 너무 많아지면 안됨!
mydb.close()
</code></pre>
</li>
</ul>
<h1 id="aws-rdsdatabase-1-연결">AWS RDS(database-1) 연결</h1>
<p>remote = mysql.connector.connect(
    host = &quot;database-1.cpys04aeky7e.ap-northeast-2.rds.amazonaws.com&quot;,
    port= 3306, #원격이니까
    user = &quot;admin&quot;,
    password = &quot;<password>&quot;
    #데이터베이스 지정해서 접근하려면, database=&quot;<databasename>&quot;
)</p>
<pre><code>## 3. 데이터베이스 테이블 작업하기
### 1) CREATE TABLE 테이블 생성
```python
cur = remote.cursor()
cur.execute(&quot;CREATE TABLE sql_file (id int, filename varchar(16))&quot;)</code></pre><p>=&gt; 터미널에서 <code>desc sql_file</code>로 확인해보면, 생성되어 있음</p>
<pre><code class="language-sql">mysql&gt; desc sql_file;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id       | int         | YES  |     | NULL    |       |
| filename | varchar(16) | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+
2 rows in set (0.02 sec)</code></pre>
<h3 id="2-drop-table-테이블-삭제">2) DROP TABLE 테이블 삭제</h3>
<pre><code class="language-python">cur = remote.cursor()
cur.execute(&quot;DROP TABLE sql_file&quot;)</code></pre>
<p>=&gt; 터미널에서 <code>desc sql_file</code>로 확인해보면, 존재하지 않아 오류 발생</p>
<pre><code class="language-sql">mysql&gt; desc sql_file;
ERROR 1146 (42S02): Table &#39;zerobase.sql_file&#39; doesn&#39;t exist</code></pre>
<h3 id="3-sql-file-실행">3) SQL File 실행</h3>
<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/262818e3-0843-474d-bfff-a86f604e82e5/image.png" alt=""></p>
<pre><code class="language-python">cur = remote.cursor()
sql = open(&quot;test03.sql&quot;).read()
cur.execute(sql)</code></pre>
<p>cursor 생성 -&gt; sql파일을 open 및 read 한 후 -&gt; cursor에서 sql을 실행</p>
<pre><code class="language-sql">mysql&gt; desc sql_file;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id       | int         | YES  |     | NULL    |       |
| filename | varchar(16) | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+
2 rows in set (0.01 sec)</code></pre>
<p>=&gt; 테이블이 잘 생성되어 있음을 확인</p>
<h3 id="4-여러-query가-담긴-sql-file-실행">4) 여러 Query가 담긴 SQL File 실행</h3>
<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/0bd0066f-f4a3-405d-a979-e0a80547af25/image.png" alt=""></p>
<pre><code class="language-python">cur = remote.cursor()
sql = open(&quot;test04.sql&quot;).read()
#multi=True 옵션을 주면 sql에 담긴 것을 여러 번 실행하게 됨.
for result_iterator in cur.execute(sql, multi=True): #여러번 실행하는 것을 result_iterator로 받아옴
    if result_iterator.with_rows: #결과값이 여러 개인 경우에는
        print(result_iterator.fetchall()) #fetchall: 결과를 모두 받아와서 찍음
    else:
        print(result_iterator.statement) 

remote.commit() #database에 적용하기 위한 명령
remote.close()

....
INSERT INTO sql_file VALUE (1, &quot;test01.sql&quot;)
INSERT INTO sql_file VALUE (2, &quot;test02.sql&quot;)
INSERT INTO sql_file VALUE (3, &quot;test03.sql&quot;)
INSERT INTO sql_file VALUE (4, &quot;test04.sql&quot;)</code></pre>
<p>잘 생성되어있는지 확인해보자!</p>
<pre><code class="language-sql">mysql&gt; select * from sql_file;
+------+------------+
| id   | filename   |
+------+------------+
|    1 | test01.sql |
|    2 | test02.sql |
|    3 | test03.sql |
|    4 | test04.sql |
+------+------------+
4 rows in set (0.02 sec)</code></pre>
<p>=&gt; 테이블이 안에 값이 잘 들어가졌음을 확인</p>
<h3 id="5-fetch-all로-select-조회한-데이터-python에서-담기">5) Fetch All로 Select 조회한 데이터 python에서 담기</h3>
<ul>
<li>참고) cursor.execute를 통해 데이터를 가져올 때, 읽어올 데이터 양이 많은 경우 buffered=True 옵션을 줘야 함<pre><code class="language-python">cur = remote.cursor(buffered=True) 
# buffered=True: 읽어올 데이터 양이 많은 경우
cur.execute(&quot;SELECT * FROM sql_file&quot;)
</code></pre>
</li>
</ul>
<p>result = cur.fetchall()</p>
<p>print(&quot;1) print(result):&quot;, result) # 한번에 다 출력되어서 나옴</p>
<p>print(&quot;------2) 한줄씩 출력해보기------&quot;)
#한줄씩 출력해보기
for result_iterator in result:
    print(result_iterator) </p>
<p>remote.close()</p>
<p>...</p>
<p>1) print(result): [(1, &#39;test01.sql&#39;), (2, &#39;test02.sql&#39;), (3, &#39;test03.sql&#39;), (4, &#39;test04.sql&#39;)]
------2) 한줄씩 출력해보기------
(1, &#39;test01.sql&#39;)
(2, &#39;test02.sql&#39;)
(3, &#39;test03.sql&#39;)
(4, &#39;test04.sql&#39;)</p>
<pre><code>## 6) Select 조회하여 검색한 결과를 Pandas로 읽기
```python
import pandas as pd
df = pd.DataFrame(result)
df.head()
...
    0    1
0    1    test01.sql
1    2    test02.sql
2    3    test03.sql
3    4    test04.sql</code></pre><h2 id="테이블에-데이터-입력-commit">테이블에 데이터 입력: commit()</h2>
<ul>
<li>commit(): database에 적용하기 위한 명령. 즉, commit()하는 순간 데이터에 적용됨.<ul>
<li>for문이 모두 종료되고 나서 commit을 하게 될 경우, for문 중간에 오류가 났을 때 모두 적용되지 않을 수 있음.</li>
<li>for문 중간에 한줄씩 완성될 때마다 commit을 하게 될 경우, 오류가 발생하기 전까지는 모두 적용시킬 수 있음.<pre><code class="language-python">cur = remote.cursor(buffered=True) 
cur.execute()
sql = &quot;INSERT INTO police_station VALUES (%s, %s)&quot; 
# %s: string으로 받겠다는 뜻
</code></pre>
</li>
</ul>
</li>
</ul>
<p>for i, row in df.iterrows():
    cur.execute(sql, tuple(row)) 
    #df 한줄씩 담긴 string 값 두개를 sql에 담아서 실행
    # =&gt; 즉 df의 값을 police_station 테이블에 넣음
    print(tuple(row))
    remote.commit() </p>
<h1 id="데이터-잘-들어갔는지-확인해보기">데이터 잘 들어갔는지 확인해보기</h1>
<p>cur.execute(&quot;SELECT * FROM police_station&quot;)
result = cur.fetchall()
for row in result:
    print(row)
```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS RDS 생성,  SQL File 실행/백업/복구]]></title>
            <link>https://velog.io/@sss_yeonii/AWS-RDS-%EC%83%9D%EC%84%B1-SQL-File-%EC%8B%A4%ED%96%89%EB%B0%B1%EC%97%85%EB%B3%B5%EA%B5%AC</link>
            <guid>https://velog.io/@sss_yeonii/AWS-RDS-%EC%83%9D%EC%84%B1-SQL-File-%EC%8B%A4%ED%96%89%EB%B0%B1%EC%97%85%EB%B3%B5%EA%B5%AC</guid>
            <pubDate>Sat, 27 Jul 2024 14:07:31 GMT</pubDate>
            <description><![CDATA[<h1 id="chapter-11-aws-rds">[Chapter 11.] AWS RDS</h1>
<h2 id="aws-rds란">AWS RDS란?</h2>
<ul>
<li>AWS RDS: Amazon Relational Database Service<ul>
<li>아마존에서 제공하는 관계형 데이터베이스 서비스</li>
<li>Cloud 상에 데이터베이스 구축</li>
</ul>
</li>
<li>AWS 회원가입: <code>https://portal.aws.amazon.com/billing/signup#/start</code><h2 id="aws-rds에서-mysql-rds-생성-후-원격으로-접속하기">AWS RDS에서 MySQL RDS 생성 후 원격으로 접속하기</h2>
</li>
<li>서비스 중 RDS 선택 -&gt; 데이터베이스 생성 </li>
<li>DB 식별자 선택 -&gt; 보안 그룹 ID 클릭 -&gt; 인바운드 규칙 추가하여 외부에서도 접근 가능하도록 설정</li>
<li>원격으로(=외부에서) MySQL RDS 접속하는 방법<ul>
<li>터미널: <code>mysql -h &quot;엔드포인트&quot; -P 포트 -u &lt;마스터 사용자 이름:admin&gt; -p</code> 후 root pw 입력</li>
<li>참고 내 정보) <code>mysql -h &quot;database-1.cpys04aeky7e.ap-northeast-2.rds.amazonaws.com&quot; -P 3306 -u admin -p</code>  (&quot;쌍따옴표&quot;를 붙이지 않아도 됨)</li>
</ul>
</li>
<li>AWS RDS 중지<ul>
<li>프리 버전은 750시간 사용할 수 있다는 제약 사항이 있어, 사용하지 않을 때는 중지하자!</li>
<li>DB식별자 체크(선택) -&gt; 상단 작업: 중지 클릭 -&gt; 스냅샷 생성: 아니요<ul>
<li>최대 7일 동안 중지 가능함. 즉, 7일 이후에는 자동으로 다시 시작함. </li>
</ul>
</li>
</ul>
</li>
<li>AWS RDS 다시 시작하는 방법<ul>
<li>DB 식별자 페이지 들어감 -&gt; 상단 작업: 시작 클릭<h1 id="chapter-12-sql-file">[Chapter 12.] SQL File</h1>
<h2 id="sql-file-실행하기">SQL File 실행하기</h2>
</li>
</ul>
</li>
<li>SQL File: SQL 쿼리를 모아놓은 파일<h3 id="실행-방법1-로그인-이후">실행 방법1. 로그인 이후</h3>
</li>
<li>VS Code 실행 -&gt; sql_ws 폴더 오픈: test01.sql로 파일 생성 -&gt; 상단 Terminal에서 New Terminal 실행<pre><code>% cd sql_ws #sql_ws 폴더 위치로 이동
sql_ws % mysql -u root -p zerobase  # zerobase 데이터베이스에 바로 접속
mysql&gt; source test01.sql  #zerobase 데이터베이스에 생성한 test01.sql 파일을 넣겠다는 뜻 = SQL File 실행
desc police_station; #결과 확인</code></pre><h3 id="실행-방법1-외부에서-바로-실행">실행 방법1. 외부에서 바로 실행</h3>
<code>% mysql -u username -p database &lt; &lt;/path/filename.sql&gt;</code><pre><code>sql_ws % mysql -u root -p zerobase &lt; test02.sql #zerobase 데이터베이스에 생성한 test02.sql 파일을 넣겠다는 뜻 = SQL File 실행
desc crime_status; #결과 확인</code></pre><h2 id="database-backup">Database Backup</h2>
</li>
<li>SQL File로 Database를 백업할 수 있다<pre><code>% mysqldump -u username -p dbname &gt; backup.sql #특정 Database Backup
# dbname에 있는 테이블들을 backup.sql이라는 이름의 SQL File로 백업하여 생성하는 것
% mysqldump -u username -p --all-databases &gt; backup.sql #모든 Database Backup</code></pre></li>
<li><blockquote>
<p>VSCode에서 backup.sql 확인: 백업한 시점의 데이터가 확인됨 (실습파일명: zerobase.sql)</p>
</blockquote>
<h2 id="database-backup-restore">Database Backup Restore</h2>
<h3 id="전체-zerobase-데이터베이스-자체-백업복구">전체 zerobase 데이터베이스 자체 백업/복구</h3>
</li>
<li>데이터베이스를 백업한 SQL File을 실행하여 그 시점으로 복구하거나 이전할 수 있다(SQL File 실행 방법과 동일)<pre><code class="language-sql"># 외부 터미널에서 생성해둔 나의 AWS RDS 접근
mysql -h &quot;database-1.cpys04aeky7e.ap-northeast-2.rds.amazonaws.com&quot; -P 3306 -u admin -p
use zerobase;
</code></pre>
</li>
</ul>
<h1 id="local에-있던-table들을-원격으로-aws-rds에-백업해두기">local에 있던 table들을 원격으로 AWS RDS에 백업해두기</h1>
<h1 id="aws-rdsdatabase-1의-zerobase-데이터베이스를-복원">AWS RDS(database-1)의 zerobase 데이터베이스를 복원</h1>
<p>source zerobase.sql </p>
<pre><code>
### Table 단위 백업: tablename을 명시하여 backupname.sql로 백업
```sql
sql_ws % mysqldump -u username -p dbname tablename &gt; backupname.sql
# celeb.sql로 celeb 테이블만 백업
sql_ws % mysqldump -u root -p zerobase celeb &gt; celeb.sql

# AWS RDS 재접속 후 celeb 삭제
mysql -h &quot;database-1.cpys04aeky7e.ap-northeast-2.rds.amazonaws.com&quot; -P 3306 -u admin -p zerobase
drop table celeb;

# AWS RDS의 zerobase에서 celeb 복구
source celeb.sql;

mysql&gt; show tables;
+--------------------+
| Tables_in_zerobase |
+--------------------+
| celeb              |
| crime_status       |
| police_station     |
| snl_show           |
| test1              |
| test2              |
+--------------------+
6 rows in set (0.02 sec)</code></pre><h3 id="table-schema-backup">Table Schema Backup</h3>
<ul>
<li>데이터를 제외하고 테이블 생성 쿼리(규칙)만 백업할 수 있다 =&gt; -d 옵션</li>
<li>zerobase 데이터베이스에 snl_show 테이블을 SQL File인 snl.sql로 Backup하기<pre><code class="language-sql">#특정 Table Schema Backup
% mysqldump -d -u username -p dbname tablename &gt; backupname.sql 
#모든 Table Schema Backup
% mysqldump -d -u username -p dbname &gt; backupname.sql 
</code></pre>
</li>
</ul>
<h1 id="local-데이터베이스에서-snl_show-테이블의-schema만-백업">Local 데이터베이스에서 snl_show 테이블의 Schema만 백업</h1>
<p>sql_ws % mysqldump -d -u root -p zerobase snl_show &gt; snl.sql
```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[MySQL Database] Table 생성,INSERT, SELECT, WHERE, UPDATE, DELETE, ORDER BY, 비교/논리 연산자, UNION, JOIN, CONCAT, ALIAS, DISTINCT, LIMIT]]></title>
            <link>https://velog.io/@sss_yeonii/MySQL-Database-Table-%EC%83%9D%EC%84%B1INSERT-SELECT-WHERE-UPDATE-DELETE-ORDER-BY-%EB%B9%84%EA%B5%90%EB%85%BC%EB%A6%AC-%EC%97%B0%EC%82%B0%EC%9E%90-UNION-JOIN-CONCAT-ALIAS-DISTINCT-LIMIT</link>
            <guid>https://velog.io/@sss_yeonii/MySQL-Database-Table-%EC%83%9D%EC%84%B1INSERT-SELECT-WHERE-UPDATE-DELETE-ORDER-BY-%EB%B9%84%EA%B5%90%EB%85%BC%EB%A6%AC-%EC%97%B0%EC%82%B0%EC%9E%90-UNION-JOIN-CONCAT-ALIAS-DISTINCT-LIMIT</guid>
            <pubDate>Sat, 27 Jul 2024 12:07:44 GMT</pubDate>
            <description><![CDATA[<h1 id="chapter-02-database-사용해보기">[Chapter 02.] Database 사용해보기</h1>
<h2 id="database-관리">Database 관리</h2>
<h3 id="database-조회">Database 조회</h3>
<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/aa679bec-aded-454e-95e4-27b146b887b2/image.png" alt=""></p>
<ul>
<li><code>show databases;</code> MySQL에 있는 Databases 목록 확인</li>
<li><code>;</code>: 즉시 실행</li>
</ul>
<h3 id="database-생성">Database 생성</h3>
<ul>
<li><code>create database dbname;</code>
<img src="https://velog.velcdn.com/images/sss_yeonii/post/28f575e8-801a-400c-b933-3f63d68c23ee/image.png" alt=""></li>
</ul>
<h3 id="database-사용">Database 사용</h3>
<ul>
<li><code>use dbname;</code> 해당 데이터베이스로 이동(=사용)</li>
</ul>
<h3 id="database-삭제">Database 삭제</h3>
<ul>
<li><code>drop database dbname;</code> </li>
</ul>
<hr>
<h2 id="user-관리">User 관리</h2>
<h3 id="user-조회">User 조회</h3>
<ul>
<li>사용자 정보는 mysql에서 관리하므로 일단 mysql 데이터베이스로 이동 후 조회<pre><code class="language-sql">use mysql;
SELECT host, user FROM user;</code></pre>
<img src="https://velog.velcdn.com/images/sss_yeonii/post/2e10822e-6efd-4fa8-97ad-555bc586fe0f/image.png" alt=""><h3 id="user-생성---localhost">User 생성 - localhost</h3>
</li>
</ul>
<ol>
<li>현재 PC에서만 접속 가능한 사용자를 비밀번호와 함께 생성
<code>CREATE USER &#39;username&#39;@&#39;localhost&#39; identified by &#39;password&#39;;</code></li>
</ol>
<ul>
<li><code>CREATE USER &#39;username&#39;</code>: username이라는 USER를 생성</li>
<li><code>@&#39;localhost&#39;</code>: 현재 PC에서만 접속 가능한 유저를 생성</li>
<li><code>identified by &#39;passworkd&#39;</code>: password를 입력한 사용자만 접속 가능
<img src="https://velog.velcdn.com/images/sss_yeonii/post/54ce32ea-29b6-4bf4-b5bb-0eca4cb2b9c1/image.png" alt=""></li>
</ul>
<ol start="2">
<li>외부에서 접속 가능한 사용자를 비밀번호와 함께 생성
<code>CREATE USER &#39;username&#39;@&#39;%&#39; identified by &#39;password&#39;;</code></li>
</ol>
<ul>
<li><code>@&#39;%&#39;</code>: 외부에서 접속 가능한 유저를 생성
<img src="https://velog.velcdn.com/images/sss_yeonii/post/f6b17aa7-7e05-463c-bbf1-abff93e94aa7/image.png" alt="">
=&gt; 이름(username)이 같지만 호스트 정보가 다르면 생성 가능<h3 id="user-삭제">User 삭제</h3>
접근 범위에 따라 같은 이름의 사용자여도 별도로 삭제
<code>DROP USER &#39;username&#39;@&#39;localhost&#39;</code>
<code>DROP USER &#39;username&#39;@&#39;%&#39;</code>
<img src="https://velog.velcdn.com/images/sss_yeonii/post/35e6fdfe-464c-4022-81ca-c7ec614fffb5/image.png" alt=""></li>
</ul>
<hr>
<h2 id="user-권한-관리">User 권한 관리</h2>
<h3 id="실습환경-만들기1---database-만들기">실습환경 만들기1 - Database 만들기</h3>
<p>1) 권한 관리를 실습하기 위한 Database (testdb) 생성
2) 사용자 (id: noma@localhost, password: 1234) 생성</p>
<ul>
<li>사용자 정보는 mysql에서 관리하고 있기 때문에 use mysql을 (이동)해주고 유저 생성<h3 id="user-권한-확인">User 권한 확인</h3>
현재 PC에서 접근 가능한 유저의 권한 확인
<code>SHOW GRANTS FOR &#39;username&#39;@&#39;localhost&#39;;</code>
<img src="https://velog.velcdn.com/images/sss_yeonii/post/47a363c4-47d9-434a-b668-99762dd8b31d/image.png" alt=""><h3 id="user-권한-부여">User 권한 부여</h3>
사용자에게 특정 데이터베이스의 모든 권한 부여
<code>GRANT ALL ON dbname.* to &#39;username&#39;@&#39;localhost&#39;;</code>
<img src="https://velog.velcdn.com/images/sss_yeonii/post/47390909-458c-41cc-97a4-4a5a3f7fcbf8/image.png" alt="">
(참고) <code>FLUSH PRIVILEGES;</code> 수정 내용이 적용되지 않은 경우 새로고침<h3 id="user-권한-삭제">User 권한 삭제</h3>
사용자에게 특정 데이터베이스의 모든 권한 삭제
<code>REVOKE ALL ON dbname.* from &#39;username&#39;@&#39;localhost&#39;;</code>
<img src="https://velog.velcdn.com/images/sss_yeonii/post/9ceb5a88-a0e0-403a-b503-64bdacad57ee/image.png" alt=""></li>
</ul>
<hr>
<h2 id="실습환경-만들기">[실습환경 만들기]</h2>
<h3 id="zerobase라는-database-생성">zerobase라는 Database 생성</h3>
<p><code>create database zerobase default character set utf8mb4;</code></p>
<ul>
<li><code>default character set utf8mb4;</code>: zerobase라는 데이터베이스는 utf8mb4(다국어+이모지문자)를 지원할 거라고 정의한 것</li>
</ul>
<hr>
<h1 id="chapter-03-table-기초">[Chapter 03.] Table 기초</h1>
<h3 id="table-생성">Table 생성</h3>
<ul>
<li>Table란? 데이터베이스 안에서 실제 데이터가 저장되는 형태, 행과 열로 구성된 데이터 모음</li>
<li>Table 생성<pre><code class="language-sql">CREATE TABLE tablename
(
  columnname datatype,
  columnname datatype,
  ...
)</code></pre>
<h3 id="table-조회">Table 조회</h3>
</li>
<li><code>show tables;</code> 현재까지 생성된 테이블 조회
<img src="https://velog.velcdn.com/images/sss_yeonii/post/ca2bec9c-7781-4d85-aab7-17845f57b714/image.png" alt=""></li>
<li><code>DESC tablename</code>: 테이블 구조(정보) 조회(DESC: description)
<img src="https://velog.velcdn.com/images/sss_yeonii/post/273eb135-2f24-478b-81ec-5de6f936cebd/image.png" alt=""></li>
<li>field: 컬럼</li>
<li>type: 데이터 타입</li>
<li>null: null을 허용하느냐 (yes가 디폴트 설정)</li>
<li>default: 값이 비어있을 때 자동으로 채우는 값 (null이 디폴트 설정)<h3 id="table-정보-변경">Table 정보 변경</h3>
</li>
<li>테이블 이름 변경: rename<pre><code class="language-sql">ALTER TABLE tablename  #tablename이라는 테이블을 변경할 것이다
RENAME new_tablename #new_tablename으로 이름을 변경해라</code></pre>
<img src="https://velog.velcdn.com/images/sss_yeonii/post/62c9b724-42b4-4d45-9304-262d23e4a580/image.png" alt=""></li>
<li>테이블 컬럼 추가: add column<pre><code class="language-sql">ALTER TABLE tablename  
ADD COLUMN columnname datatype; #columnname이라는 이름의 컬럼 추가</code></pre>
<img src="https://velog.velcdn.com/images/sss_yeonii/post/baf04f40-b56b-4c2c-81c4-a4f0db26229c/image.png" alt=""></li>
<li>테이블 컬럼의 데이터타입 수정: modify<pre><code class="language-sql">ALTER TABLE tablename  
MODIFY COLUMN columnname new_datatype; </code></pre>
</li>
<li>테이블 컬럼의 이름/데이터타입 변경: change column <pre><code class="language-sql">ALTER TABLE tablename  
CHANGE COLUMN old_columnname new_columnname new_datatype; </code></pre>
<img src="https://velog.velcdn.com/images/sss_yeonii/post/5d2cedd8-c8cb-431c-ac24-6ea163da8c69/image.png" alt=""></li>
<li>테이블 컬럼 삭제: drop column<pre><code class="language-sql">ALTER TABLE tablename  
DROP COLUMN columnname; </code></pre>
<img src="https://velog.velcdn.com/images/sss_yeonii/post/5f0288fd-0381-436c-a9db-2c7c158b1b29/image.png" alt=""></li>
<li>테이블 삭제: drop table
<img src="https://velog.velcdn.com/images/sss_yeonii/post/e1fee7d9-9be8-46d3-b5af-cbbd1a7f86af/image.png" alt=""></li>
</ul>
<hr>
<h1 id="chapter-04-insert-select-where-update-delete">[Chapter 04.] INSERT, SELECT, WHERE, UPDATE, DELETE</h1>
<h4 id="실습할-테이블-만들기">실습할 테이블 만들기</h4>
<pre><code class="language-sql">mysql&gt; desc person;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | YES  |     | NULL    |       |
| name  | varchar(16) | YES  |     | NULL    |       |
| age   | int         | YES  |     | NULL    |       |
| sex   | char(1)     | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)</code></pre>
<h3 id="insert---데이터-추가">INSERT - 데이터 추가</h3>
<ul>
<li>INSERT: 데이터를 추가하는 명령어</li>
<li>입력한 컬럼 이름의 순서와 값의 순서가 일치해야 함!</li>
<li>모든 칼럼값을 추가하는 경우에는 컬럼 이름을 지정하지 않아도 되지만, 입력하는 값 순서가 테이블의 컬럼 순서와 일치해야 함<pre><code class="language-sql">INSERT INTO tablename (column1, column2, ...)
VALUES (value1, value2, ...);
혹은 
INSERT INTO tablename 
VALUES (value1, value2, ...);</code></pre>
<img src="https://velog.velcdn.com/images/sss_yeonii/post/e1303970-a46d-4d3b-b70e-cd8b82a1cf4f/image.png" alt=""><img src="https://velog.velcdn.com/images/sss_yeonii/post/4df9b1d2-7f4d-456d-94c1-425dfb4fe04a/image.png" alt=""></li>
</ul>
<h3 id="select---데이터-조회">SELECT - 데이터 조회</h3>
<ul>
<li>SELECT: 테이블 내의 특정 컬럼에 대한 데이터를 조회<pre><code class="language-sql">SELECT column1, column2, ...   # SELECT *: 전체 컬럼 가져오기
FROM tablename;</code></pre>
<h3 id="where---특정-조건의-데이터-조회">WHERE - 특정 조건의 데이터 조회</h3>
</li>
<li>SQL문에 조건을 추가하며 SELECT뿐만 아니라 UPDATE, DELETE에도 사용 가능<pre><code class="language-sql">SELECT column1, column2, ...   # SELECT *: 전체 컬럼 가져오기
FROM tablename
WHERE condition; #WHERE sex=&#39;F&#39; / WHERE age&gt;45</code></pre>
<img src="https://velog.velcdn.com/images/sss_yeonii/post/d1e3fbde-1abb-4f49-8507-b32bc27ada85/image.png" alt=""></li>
</ul>
<h3 id="update---데이터-수정">UPDATE - 데이터 수정</h3>
<pre><code class="language-sql">UPDATE tablename
SET column1 = value1, column2 = value2, ...
WHERE condition; 

# 이효리의 나이를 23세로 수정
update person
    -&gt; set age=23 
    -&gt; where name=&#39;이효리&#39;;</code></pre>
<h3 id="delete---데이터-삭제">DELETE - 데이터 삭제</h3>
<pre><code class="language-sql"># WHERE 조건을 만족하는 데이터를 삭제
DELETE FROM tablename
WHERE condition; </code></pre>
<hr>
<h1 id="chapter-05-order-by">[Chapter 05.] Order By</h1>
<h3 id="order-by">Order By</h3>
<ul>
<li><p>select문에서 데이터를 특정 컬럼 기준으로 오름차순(ASC) 혹은 내림차순(DESC) 정렬</p>
</li>
<li><p>ASC를 생략해도 디폴트가 오름차순 정렬임</p>
</li>
<li><p>Order by col1, col2 로 두개 이상의 컬럼 지정할 경우, col1의 데이터 값이 동일할 때 col2 기준으로 다시 정렬함. (col1로 정렬한 후 col2로 한번 더 정렬)</p>
<pre><code class="language-sql">SELECT col1, col2, ...
FROM tablename
ORDER BY col1, col2, ... ASC | DESC;</code></pre>
</li>
<li><p><code>order by age desc, name asc;</code>: age 내림차순 정렬한 뒤 name 오름차순으로 정렬</p>
<h1 id="chapter-06-comparison-operators비교연산자">[Chapter 06.] Comparison Operators(비교연산자)</h1>
<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/e2c50ee0-4262-40d6-87e5-bdf3dbbbce84/image.png" alt=""></p>
</li>
<li><p><code>A &lt;&gt; B</code>: A와 B가 같지 않다(A가 B보다 크거나 작다)</p>
</li>
<li><p><code>A !=B</code>: A와 B가 같지 않다</p>
<h3 id="예제">예제</h3>
<pre><code class="language-sql">mysql&gt; use zerobase;
Database changed
mysql&gt; create table celeb(
  -&gt; id int not null auto_increment primary key,
  -&gt; name varchar(32) not null default &#39;&#39;,
  -&gt; birthday date,
  -&gt; age int,
  -&gt; sex char(1),
  -&gt; job_title varchar(32),
  -&gt; agency varchar(32)
  -&gt; );
Query OK, 0 rows affected (0.01 sec)
</code></pre>
</li>
</ul>
<p>mysql&gt; desc celeb;
+-----------+-------------+------+-----+---------+----------------+
| Field     | Type        | Null | Key | Default | Extra          |
+-----------+-------------+------+-----+---------+----------------+
| id        | int         | NO   | PRI | NULL    | auto_increment |
| name      | varchar(32) | NO   |     |         |                |
| birthday  | date 타입&quot; birthday &gt; 19891231        | YES  |     | NULL    |                |
| age       | int         | YES  |     | NULL    |                |
| sex       | char(1)     | YES  |     | NULL    |                |
| job_title | varchar(32) | YES  |     | NULL    |                |
| agency    | varchar(32) | YES  |     | NULL    |                |
+-----------+-------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)</p>
<h1 id="예제-테이블-생성">예제 테이블 생성</h1>
<p>INSERT INTO celeb VALUES (1, &#39;아이유&#39;, &#39;1993-05-16&#39;, 29, &#39;F&#39;, &#39;가수, 텔런트&#39;, &#39;EDAM엔터테인먼트&#39;);
INSERT INTO celeb VALUES (2, &#39;이미주&#39;, &#39;1994-09-23&#39;, 28, &#39;F&#39;, &#39;가수&#39;, &#39;울림엔터테인먼트&#39;);
INSERT INTO celeb VALUES (3, &#39;송강&#39;, &#39;1994-04-23&#39;, 28,&#39;M&#39;, &#39;텔런트&#39;, &#39;나무엑터스&#39;);
INSERT INTO celeb VALUES (4, &#39;강동원&#39;, &#39;1981-01-18&#39;, 41, &#39;M&#39;,&#39;영화배우, 텔런트&#39;, &#39;YG엔터테인먼트&#39;);
INSERT INTO celeb VALUES (5, &#39;유재석&#39;, &#39;1972-08-14&#39;, 50, &#39;M&#39;, &#39;MC, 개그맨&#39;, &#39;안테나&#39;);
INSERT INTO celeb VALUES (6, &#39;차승원&#39;, &#39;1970-06-07&#39;, 48, &#39;M&#39;, &#39;영화배우, 모델&#39;, &#39;YG엔터테인먼트&#39;);
INSERT INTO celeb VALUES (7, &#39;이수현&#39;, &#39;1999-05-04&#39;, 23, &#39;F&#39;, &#39;가수&#39;, &#39;YG엔터테인먼트&#39;);</p>
<h1 id="age-내림차순-name-오름차순으로-celeb-정렬">age 내림차순, name 오름차순으로 celeb 정렬</h1>
<p>mysql&gt; select *
    -&gt; from celeb
    -&gt; order by age desc, name asc;
+----+-----------+------------+------+------+-------------------------+--------------------------+
| id | name      | birthday   | age  | sex  | job_title               | agency                   |
+----+-----------+------------+------+------+-------------------------+--------------------------+
|  5 | 유재석    | 1972-08-14 |   50 | M    | MC, 개그맨              | 안테나                   |
|  6 | 차승원    | 1970-06-07 |   48 | M    | 영화배우, 모델          | YG엔터테인먼트           |
|  4 | 강동원    | 1981-01-18 |   41 | M    | 영화배우, 텔런트        | YG엔터테인먼트           |
|  1 | 아이유    | 1993-05-16 |   29 | F    | 가수, 텔런트            | EDAM엔터테인먼트         |
|  3 | 송강      | 1994-04-23 |   28 | M    | 텔런트                  | 나무엑터스               |
|  2 | 이미주    | 1994-09-23 |   28 | F    | 가수                    | 울림엔터테인먼트         |
|  7 | 이수현    | 1999-05-04 |   23 | F    | 가수                    | YG엔터테인먼트           |
+----+-----------+------------+------+------+-------------------------+--------------------------+
7 rows in set (0.00 sec)</p>
<h1 id="age가-50-미만인-sex-agency-name-age-컬럼의-celeb-데이터를">age가 50 미만인 sex, agency, name, age 컬럼의 celeb 데이터를</h1>
<h1 id="agency-내림차순-정렬한-후-name-오름차순으로-정렬">agency 내림차순 정렬한 후 name 오름차순으로 정렬</h1>
<p>mysql&gt; select sex, agency, name, age
    -&gt; from celeb
    -&gt; where age&lt;50
    -&gt; order by agency desc, name asc;
+------+--------------------------+-----------+------+
| sex  | agency                   | name      | age  |
+------+--------------------------+-----------+------+
| F    | 울림엔터테인먼트         | 이미주    |   28 |
| M    | 나무엑터스               | 송강      |   28 |
| M    | YG엔터테인먼트           | 강동원    |   41 |
| F    | YG엔터테인먼트           | 이수현    |   23 |
| M    | YG엔터테인먼트           | 차승원    |   48 |
| F    | EDAM엔터테인먼트         | 아이유    |   29 |
+------+--------------------------+-----------+------+
6 rows in set (0.00 sec)</p>
<pre><code>
# [Chapter 07.] Logical Operators(논리연산자)
![](https://velog.velcdn.com/images/sss_yeonii/post/96e33230-ced1-4879-8729-faca6f4a5619/image.png)
- and가 or 보다 조건 우선순위가 높음. and가 먼저 수행된 다음에 or가 수행됨.
- 홀수 조건: (id%2)=1 / 짝수 조건: (id%2)=0
- date 타입: birthday &gt; 19891231 와 같이 하여 1990년 이후를 조건 걸 수 있음
- `WHERE columnname BETWEEN val1 AND val2`는 `val1 이상 val2 이하`와 동일
- `WHERE columnname IN (val1, val2)`는 `col=val1 or col=val2`와 동일
- `WHERE columnname LIKE pattern`
   - `LIKE`: 대소문자 구분 없이 반환. (a에 대해 검색하면 A도 나옴)
   - `YG%`: &#39;YG&#39;로 시작하는 데이터
   - `%엔터테인먼트`: &#39;엔터테인먼트&#39;로 끝나는 데이터
   - `%가수%`: &#39;가수&#39;가 포함된 데이터
   - `_G%`: 두번째 글자가 G인 데이터
   - `가_%`: &#39;가&#39;로 시작하고 최소 2글자 이상인 데이터 (언더바_로 글자수 확보)
   - `가____%`:&#39;가&#39;로 시작하고 최소 5글자 이상인 데이터
   - `영%모델`: &#39;영&#39;으로 시작하고 &#39;모델&#39;로 끝나는 데이터
```sql
# 소속사가 YG이거나 나무엑터스인 연예인 중, 나이가 30 미만인 데이터 검색
mysql&gt; select * from celeb
    -&gt; where (agency=&#39;YG엔터테인먼트&#39; or agency=&#39;나무엑터스&#39;) and age&lt;30;
+----+-----------+------------+------+------+-----------+----------------------+
| id | name      | birthday   | age  | sex  | job_title | agency               |
+----+-----------+------------+------+------+-----------+----------------------+
|  3 | 송강      | 1994-04-23 |   28 | M    | 텔런트    | 나무엑터스           |
|  7 | 이수현    | 1999-05-04 |   23 | F    | 가수      | YG엔터테인먼트       |
+----+-----------+------------+------+------+-----------+----------------------+
2 rows in set (0.00 sec)

# id가 홀수이면서 남자이거나 / id가 짝수이면서 YG인 연예인 (나이순 정렬)
mysql&gt; select * from celeb where  ((id%2)=1 and sex=&#39;M&#39;) or ((id%2)=0 and agency=&#39;YG엔터테인먼트&#39;)
    -&gt; order by age;
+----+-----------+------------+------+------+-------------------------+----------------------+
| id | name      | birthday   | age  | sex  | job_title               | agency               |
+----+-----------+------------+------+------+-------------------------+----------------------+
|  3 | 송강      | 1994-04-23 |   28 | M    | 텔런트                  | 나무엑터스           |
|  4 | 강동원    | 1981-01-18 |   41 | M    | 영화배우, 텔런트        | YG엔터테인먼트       |
|  6 | 차승원    | 1970-06-07 |   48 | M    | 영화배우, 모델          | YG엔터테인먼트       |
|  5 | 유재석    | 1972-08-14 |   50 | M    | MC, 개그맨              | 안테나               |
+----+-----------+------------+------+------+-------------------------+----------------------+
4 rows in set (0.00 sec)

# 나이가 20에서 40 사이인 데이터 검색
mysql&gt; select * from celeb where age between 20 and 40;
+----+-----------+------------+------+------+-------------------+--------------------------+
| id | name      | birthday   | age  | sex  | job_title         | agency                   |
+----+-----------+------------+------+------+-------------------+--------------------------+
|  1 | 아이유    | 1993-05-16 |   29 | F    | 가수, 텔런트      | EDAM엔터테인먼트         |
|  2 | 이미주    | 1994-09-23 |   28 | F    | 가수              | 울림엔터테인먼트         |
|  3 | 송강      | 1994-04-23 |   28 | M    | 텔런트            | 나무엑터스               |
|  7 | 이수현    | 1999-05-04 |   23 | F    | 가수              | YG엔터테인먼트           |
+----+-----------+------------+------+------+-------------------+--------------------------+
4 rows in set (0.00 sec)

# 생년월일이 1980년~1995년 사이가 아니면서 여자이거나, 소속사가 YG이면서 나이가 20세~45세가 아닌 데이터
mysql&gt; select * from celeb where (sex=&#39;F&#39; and not birthday between 19800101 and 19951231) or (agency=&#39;YG엔터테 인먼트&#39; and not age between 20 and 45);
+----+-----------+------------+------+------+----------------------+----------------------+
| id | name      | birthday   | age  | sex  | job_title            | agency               |
+----+-----------+------------+------+------+----------------------+----------------------+
|  6 | 차승원    | 1970-06-07 |   48 | M    | 영화배우, 모델       | YG엔터테인먼트       |
|  7 | 이수현    | 1999-05-04 |   23 | F    | 가수                 | YG엔터테인먼트       |
+----+-----------+------------+------+------+----------------------+----------------------+
2 rows in set (0.00 sec)

# &#39;아이유&#39;,&#39;송강&#39;,&#39;강동원&#39;,&#39;차승원&#39; 중에 YG 소속이 아니거나 나이가 40~50세인 사람 검색
mysql&gt; select * from celeb  where name in (&#39;아이유&#39;,&#39;송강&#39;,&#39;강동원&#39;,&#39;차승원&#39;) and (not agency=&#39;YG엔터테인먼트&#39;
or age between 40 and 50);
+----+-----------+------------+------+------+-------------------------+------------------------+
| id | name      | birthday   | age  | sex  | job_title               | agency                 |
+----+-----------+------------+------+------+-------------------------+------------------------+
|  1 | 아이유    | 1993-05-16 |   29 | F    | 가수, 텔런트            | EDAM엔터테인먼트       |
|  3 | 송강      | 1994-04-23 |   28 | M    | 텔런트                  | 나무엑터스             |
|  4 | 강동원    | 1981-01-18 |   41 | M    | 영화배우, 텔런트        | YG엔터테인먼트         |
|  6 | 차승원    | 1970-06-07 |   48 | M    | 영화배우, 모델          | YG엔터테인먼트         |
+----+-----------+------------+------+------+-------------------------+------------------------+
4 rows in set (0.00 sec)


# YG로 시작하는 소속사 이름 가진 데이터 검색
mysql&gt; select * from celeb where agency like &#39;YG%&#39;;
+----+-----------+------------+------+------+-------------------------+----------------------+
| id | name      | birthday   | age  | sex  | job_title               | agency               |
+----+-----------+------------+------+------+-------------------------+----------------------+
|  4 | 강동원    | 1981-01-18 |   41 | M    | 영화배우, 텔런트        | YG엔터테인먼트       |
|  6 | 차승원    | 1970-06-07 |   48 | M    | 영화배우, 모델          | YG엔터테인먼트       |
|  7 | 이수현    | 1999-05-04 |   23 | F    | 가수                    | YG엔터테인먼트       |
+----+-----------+------------+------+------+-------------------------+----------------------+
3 rows in set (0.00 sec)

# 직업이 하나 이상인 연예인 중 영화배우 혹은 텔런트가 아닌 연예인 검색
mysql&gt; select * from celeb where job_title like &#39;%,%&#39; and not (job_title like &#39;%영화배우%&#39; or job_title like &#39;%텔런트%&#39;);
+----+-----------+------------+------+------+---------------+-----------+
| id | name      | birthday   | age  | sex  | job_title     | agency    |
+----+-----------+------------+------+------+---------------+-----------+
|  5 | 유재석    | 1972-08-14 |   50 | M    | MC, 개그맨    | 안테나    |
+----+-----------+------------+------+------+---------------+-----------+
1 row in set (0.00 sec)</code></pre><h1 id="chapter-08-union">[Chapter 08.] Union</h1>
<h2 id="union">Union</h2>
<ul>
<li>Union이란? 여러 개의 SQL문을 합쳐서 하나의 SQL문으로 만들어주는 방법(주의: 칼럼 개수가 같아야 함)</li>
<li>UNION: 중복된 값을 제거한 후 합쳐서 보여준다</li>
<li>UNION ALL: 중복된 값도 합쳐서 모두 보여준다
```sql<h1 id="union-test2의-중복된-값인-3은-제거됨">UNION: test2의 중복된 값인 3은 제거됨.</h1>
mysql&gt; select * from test1
  -&gt; union
  -&gt; select * from test2;</li>
<li>------+
| no   |</li>
<li>------+
|    1 |
|    2 |
|    3 |
|    5 |
|    6 |</li>
<li>------+
5 rows in set (0.01 sec)</li>
</ul>
<h1 id="union-all-test2의-중복된-값인-3도-포함하여-보여줌">UNION ALL: test2의 중복된 값인 3도 포함하여 보여줌</h1>
<p>mysql&gt; select * from test1 
    -&gt; union all 
    -&gt; select * from test2;
+------+
| no   |
+------+
|    1 |
|    2 |
|    3 |
|    5 |
|    6 |
|    3 |
+------+
6 rows in set (0.00 sec)</p>
<pre><code># [Chapter 09.] Join
### 실습 테이블 생성
```sql
mysql&gt; create table snl_show(
    -&gt; id int not null auto_increment primary key,
    -&gt; season int not null,
    -&gt; episode int not null,
    -&gt; broadcast_date date,
    -&gt; host varchar(32) not null
    -&gt; );
Query OK, 0 rows affected (0.03 sec)

mysql&gt; desc snl_show;
+----------------+-------------+------+-----+---------+----------------+
| Field          | Type        | Null | Key | Default | Extra          |
+----------------+-------------+------+-----+---------+----------------+
| id             | int         | NO   | PRI | NULL    | auto_increment |
| season         | int         | NO   |     | NULL    |                |
| episode        | int         | NO   |     | NULL    |                |
| broadcast_date | date        | YES  |     | NULL    |                |
| host           | varchar(32) | NO   |     | NULL    |                |
+----------------+-------------+------+-----+---------+----------------+
5 rows in set (0.01 sec)

INSERT INTO snl_show VALUES (1, 8, 7, &#39;2020-09-05&#39;, &#39;강동원&#39; );
INSERT INTO snl_show VALUES (2, 8, 8, &#39;2020-09-12&#39;, &#39;유재석&#39;);
INSERT INTO snl_show VALUES (3, 8, 9, &#39;2020-09-19&#39;, &#39;차승원&#39;);
INSERT INTO snl_show VALUES (4, 8, 10, &#39;2020-09-26&#39;, &#39;이수현&#39;);
INSERT INTO snl_show VALUES (5, 9, 1, &#39;2021-09-04&#39;, &#39;이병헌&#39;);
INSERT INTO snl_show VALUES (6, 9, 2, &#39;2021-09-11&#39;, &#39;하지원&#39;);
INSERT INTO snl_show VALUES (7, 9, 3, &#39;2021-09-18&#39;, &#39;제시&#39;);
INSERT INTO snl_show VALUES (8, 9, 4, &#39;2021-09-25&#39;, &#39;조정석&#39;);
INSERT INTO snl_show VALUES (9, 9, 5, &#39;2021-10-02&#39;, &#39;조여정&#39;);
INSERT INTO snl_show VALUES (10, 9, 6, &#39;2021-10-09&#39;, &#39;옥주현&#39;);

mysql&gt; select * from snl_show;
+----+--------+---------+----------------+-----------+
| id | season | episode | broadcast_date | host      |
+----+--------+---------+----------------+-----------+
|  1 |      8 |       7 | 2020-09-05     | 강동원    |
|  2 |      8 |       8 | 2020-09-12     | 유재석    |
|  3 |      8 |       9 | 2020-09-19     | 차승원    |
|  4 |      8 |      10 | 2020-09-26     | 이수현    |
|  5 |      9 |       1 | 2021-09-04     | 이병헌    |
|  6 |      9 |       2 | 2021-09-11     | 하지원    |
|  7 |      9 |       3 | 2021-09-18     | 제시      |
|  8 |      9 |       4 | 2021-09-25     | 조정석    |
|  9 |      9 |       5 | 2021-10-02     | 조여정    |
| 10 |      9 |       6 | 2021-10-09     | 옥주현    |
+----+--------+---------+----------------+-----------+
10 rows in set (0.00 sec)</code></pre><h2 id="join-두-개-이상의-테이블을-결합하는-것">Join: 두 개 이상의 테이블을 결합하는 것</h2>
<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/cf19727d-74de-47b1-84cb-6c92097f8919/image.png" alt=""></p>
<h3 id="inner-join">INNER JOIN</h3>
<p>두 개의 테이블에서 공통된 요소들을 통해 결합하는 조인 방식</p>
<pre><code class="language-sql">SELECT col1, col2, ...
FROM tableA
INNER JOIN tableB   
ON tableA.column = tableB.column
WHERE condition;
#A와 B 테이블의 column 값이 동일한 데이터만 조인
#조인된 데이터에 대해 condition이 일치하는 데이터만 불러옴</code></pre>
<ul>
<li><p>실습 예제
```sql</p>
<h1 id="snl_show-호스트-출연한-celeb-기준으로-celeb-테이블과-snl_show-테이블을-inner-join">snl_show 호스트 출연한 celeb 기준으로 celeb 테이블과 snl_show 테이블을 INNER JOIN</h1>
<p>mysql&gt; select celeb.id, celeb.name, snl_show.id, snl_show.host </p>
<pre><code>-&gt; from celeb 
-&gt; inner join snl_show 
-&gt; on celeb.name = snl_show.host;</code></pre></li>
<li><p>----+-----------+----+-----------+
| id | name      | id | host      |</p>
</li>
<li><p>----+-----------+----+-----------+
|  4 | 강동원    |  1 | 강동원    |
|  5 | 유재석    |  2 | 유재석    |
|  6 | 차승원    |  3 | 차승원    |
|  7 | 이수현    |  4 | 이수현    |</p>
</li>
<li><p>----+-----------+----+-----------+
4 rows in set (0.00 sec)</p>
<pre><code>### LEFT JOIN
두 개의 테이블에서 공통 영역을 포함해 왼쪽 테이블(tableA)의 다른 데이터를 포함하는 조인 방식
```sql
SELECT col1, col2, ...
FROM tableA
LEFT JOIN tableB   
ON tableA.column = tableB.column
WHERE condition;</code></pre></li>
<li><p>실습 예제
```sql</p>
<h1 id="celeb-테이블에서-snl_showid-snl_showhost는-없기-때문에-null임">celeb 테이블에서 snl_show.id, snl_show.host는 없기 때문에 NULL임.</h1>
<p>mysql&gt; select celeb.id, celeb.name, snl_show.id, snl_show.host </p>
<pre><code>-&gt;from celeb 
-&gt; left join snl_show 
-&gt; on celeb.name = snl_show.host;</code></pre></li>
<li><p>----+-----------+------+-----------+
| id | name      | id   | host      |</p>
</li>
<li><p>----+-----------+------+-----------+
|  1 | 아이유    | NULL | NULL      |
|  2 | 이미주    | NULL | NULL      |
|  3 | 송강      | NULL | NULL      |
|  4 | 강동원    |    1 | 강동원    |
|  5 | 유재석    |    2 | 유재석    |
|  6 | 차승원    |    3 | 차승원    |
|  7 | 이수현    |    4 | 이수현    |</p>
</li>
<li><p>----+-----------+------+-----------+
7 rows in set (0.00 sec)</p>
<pre><code>### RIGHT JOIN
두 개의 테이블에서 공통 영역을 포함해 오른쪽 테이블(tableB)의 다른 데이터를 포함하는 조인 방식
```sql
SELECT col1, col2, ...
FROM tableA
RIGHT JOIN tableB   
ON tableA.column = tableB.column
WHERE condition;</code></pre></li>
<li><p>실습 예제
```sql</p>
<h1 id="snl_show-테이블에서-celebid-celebname-없기-때문에-null임">snl_show 테이블에서 celeb.id, celeb.name 없기 때문에 NULL임.</h1>
<p>mysql&gt; select celeb.id, celeb.name, snl_show.id, snl_show.host </p>
<pre><code>-&gt; from celeb 
-&gt; right join snl_show 
-&gt; on celeb.name = snl_show.host;</code></pre></li>
<li><p>------+-----------+----+-----------+
| id   | name      | id | host      |</p>
</li>
<li><p>------+-----------+----+-----------+
|    4 | 강동원    |  1 | 강동원    |
|    5 | 유재석    |  2 | 유재석    |
|    6 | 차승원    |  3 | 차승원    |
|    7 | 이수현    |  4 | 이수현    |
| NULL | NULL      |  5 | 이병헌    |
| NULL | NULL      |  6 | 하지원    |
| NULL | NULL      |  7 | 제시      |
| NULL | NULL      |  8 | 조정석    |
| NULL | NULL      |  9 | 조여정    |
| NULL | NULL      | 10 | 옥주현    |</p>
</li>
<li><p>------+-----------+----+-----------+
10 rows in set (0.01 sec)</p>
<pre><code>### FULL OUTER JOIN
두 개의 테이블에서 공통 영역을 포함해 양쪽 테이블(tableB)의 다른 데이터를 모두 포함하는 조인 방식
```sql
SELECT col1, col2, ...
FROM tableA
FULL OUTER JOIN tableB   
ON tableA.column = tableB.column
WHERE condition;</code></pre><p>=&gt; MySQL에서는 FULL OUTER JOIN을 지원하지 않아 ERROR 발생! 
=&gt; MySQL에서는 left join + union + right join으로 구현 가능</p>
</li>
<li><p>실습 예제
```sql
mysql&gt; select celeb.id, celeb.name, snl_show.id, snl_show.host from celeb left join snl_show on celeb.name = snl_show.host
  -&gt; union
  -&gt; select celeb.id, celeb.name, snl_show.id, snl_show.host from celeb right join snl_show on celeb.name = snl_show.host;</p>
</li>
<li><p>------+-----------+------+-----------+
| id   | name      | id   | host      |</p>
</li>
<li><p>------+-----------+------+-----------+
|    1 | 아이유    | NULL | NULL      |
|    2 | 이미주    | NULL | NULL      |
|    3 | 송강      | NULL | NULL      |
|    4 | 강동원    |    1 | 강동원    |
|    5 | 유재석    |    2 | 유재석    |
|    6 | 차승원    |    3 | 차승원    |
|    7 | 이수현    |    4 | 이수현    |
| NULL | NULL      |    5 | 이병헌    |
| NULL | NULL      |    6 | 하지원    |
| NULL | NULL      |    7 | 제시      |
| NULL | NULL      |    8 | 조정석    |
| NULL | NULL      |    9 | 조여정    |
| NULL | NULL      |   10 | 옥주현    |</p>
</li>
<li><p>------+-----------+------+-----------+
13 rows in set (0.01 sec)
```</p>
<h3 id="self-join">SELF JOIN</h3>
</li>
<li><p>WHERE 조건과 일치하는 FROM의 여러 테이블들을 불러옴 = INNER JOIN</p>
</li>
<li><p>각 테이블에 존재하는 칼럼명이 다르면 해당 칼럼명은 테이블명을 붙이지 않아도 됨.</p>
<pre><code class="language-sql">SELECT col1, col2, ...
FROM tableA, tableB, ...
WHERE condition;</code></pre>
</li>
<li><p>실습 예제
```sql</p>
<h1 id="inner-join과-동일한-결과">INNER JOIN과 동일한 결과</h1>
<p>mysql&gt; select celeb.id, celeb.name, snl_show.id, snl_show.host 
  -&gt; from celeb, snl_show
  -&gt; where celeb.name = snl_show.host;</p>
</li>
<li><p>----+-----------+----+-----------+
| id | name      | id | host      |</p>
</li>
<li><p>----+-----------+----+-----------+
|  4 | 강동원    |  1 | 강동원    |
|  5 | 유재석    |  2 | 유재석    |
|  6 | 차승원    |  3 | 차승원    |
|  7 | 이수현    |  4 | 이수현    |</p>
</li>
<li><p>----+-----------+----+-----------+
4 rows in set (0.00 sec)</p>
</li>
</ul>
<h1 id="celeb-연예인-중-snl_show에-host로-출연했고">celeb 연예인 중 snl_show에 host로 출연했고,</h1>
<h1 id="영화배우는-아니면서-yg-소속이거나">영화배우는 아니면서 YG 소속이거나</h1>
<h1 id="40세-이상이면서-yg-소속이-아닌">40세 이상이면서 YG 소속이 아닌</h1>
<h1 id="연예인의-이름-나이-직업-소속사-시즌-에피소드-검색">연예인의 이름, 나이, 직업, 소속사, 시즌, 에피소드 검색</h1>
<p>mysql&gt; select celeb.name, celeb.job_title, celeb.agency, snl_show.season, snl_show.episode from celeb, snl_show where celeb.name=snl_show.host and ((celeb.job_title not like &#39;%영화배우%&#39; and celeb.agency like &#39;YG%&#39;) or (celeb.age &gt;= 40 and celeb.agency not like &#39;YG%&#39;));
+-----------+---------------+----------------------+--------+---------+
| name      | job_title     | agency               | season | episode |
+-----------+---------------+----------------------+--------+---------+
| 유재석    | MC, 개그맨    | 안테나               |      8 |       8 |
| 이수현    | 가수          | YG엔터테인먼트       |      8 |      10 |
+-----------+---------------+----------------------+--------+---------+
2 rows in set (0.01 sec)</p>
<h1 id="칼럼명이-다르면-테이블명을-붙이지-않아도-됨">칼럼명이 다르면 테이블명을 붙이지 않아도 됨.</h1>
<p>mysql&gt; select snl_show.id, season, episode, name, job_title
    -&gt; from celeb, snl_show
    -&gt; where name = host;
+----+--------+---------+-----------+-------------------------+
| id | season | episode | name      | job_title               |
+----+--------+---------+-----------+-------------------------+
|  1 |      8 |       7 | 강동원    | 영화배우, 텔런트        |
|  2 |      8 |       8 | 유재석    | MC, 개그맨              |
|  3 |      8 |       9 | 차승원    | 영화배우, 모델          |
|  4 |      8 |      10 | 이수현    | 가수                    |
+----+--------+---------+-----------+-------------------------+
4 rows in set (0.00 sec)</p>
<h1 id="snl_show-출연한-celeb-중-2020-09-15-이후에-출연했거나">snl_show 출연한 celeb 중, 2020-09-15 이후에 출연했거나,</h1>
<h1 id="소속사-이름이-엔터테인먼트로-끝나지-않으면서">소속사 이름이 &#39;엔터테인먼트&#39;로 끝나지 않으면서</h1>
<h1 id="영화배우나-개그맨이-아닌-연예인의-celeb-id-name-직업-소속사-검색">영화배우나 개그맨이 아닌 연예인의 celeb id, name, 직업, 소속사 검색</h1>
<p>mysql&gt; select celeb.id, name, job_title, agency from celeb, snl_show where name=host and (broadcast_date &gt; &#39;2020-09-15&#39; or not agency like &#39;%엔터테인먼트&#39;) and not (job_title like &#39;%영화배우%&#39; or job_title like &#39;%개그맨%&#39;);
+----+-----------+-----------+----------------------+
| id | name      | job_title | agency               |
+----+-----------+-----------+----------------------+
|  7 | 이수현    | 가수      | YG엔터테인먼트       |
+----+-----------+-----------+----------------------+
1 row in set (0.00 sec)</p>
<pre><code># [Chapter 10.] Concat, Alias(as), Distinct
### Concat
- Concat이란? 여러 문자열을 하나로 합치거나 연결하는 함수
`SELECT CONCAT(&#39;string1&#39;, &#39;string2&#39;, ...) from tablename;`
```sql
mysql&gt; select concat(&#39;이름: &#39;, name) from celeb;
+--------------------------+
| concat(&#39;이름: &#39;, name)   |
+--------------------------+
| 이름: 아이유             |
| 이름: 이미주             |
| 이름: 송강               |
| 이름: 강동원             |
| 이름: 유재석             |
| 이름: 차승원             |
| 이름: 이수현             |
+--------------------------+
7 rows in set (0.00 sec)</code></pre><h3 id="alias">Alias</h3>
<ul>
<li>alias: 칼럼이나 테이블 이름에 별칭 생성 (as 생략 가능)</li>
<li>컬럼에 별칭 생성: <code>SELECT column as alias from tablename;</code></li>
<li>테이블에 별칭 생성: <code>SELECT col1, col2, ... FROM tablename as alias;</code>
```sql
mysql&gt; select name as &#39;이름&#39;, agency as &#39;소속사&#39; from celeb;</li>
<li>-----------+--------------------------+
| 이름      | 소속사                   |</li>
<li>-----------+--------------------------+
| 아이유    | EDAM엔터테인먼트         |
| 이미주    | 울림엔터테인먼트         |
| 송강      | 나무엑터스               |
| 강동원    | YG엔터테인먼트           |
| 유재석    | 안테나                   |
| 차승원    | YG엔터테인먼트           |
| 이수현    | YG엔터테인먼트           |</li>
<li>-----------+--------------------------+
7 rows in set (0.00 sec)</li>
</ul>
<h1 id="이름과-직업을-합쳐서-profile이라는-별칭으로-만들어서-검색">이름과 직업을 합쳐서 profile이라는 별칭으로 만들어서 검색</h1>
<p>mysql&gt; select concat(name, &#39;: &#39;, job_title) as profile from celeb;
+------------------------------------+
| profile                            |
+------------------------------------+
| 아이유: 가수, 텔런트               |
| 이미주: 가수                       |
| 송강: 텔런트                       |
| 강동원: 영화배우, 텔런트           |
| 유재석: MC, 개그맨                 |
| 차승원: 영화배우, 모델             |
| 이수현: 가수                       |
+------------------------------------+
7 rows in set (0.00 sec)</p>
<h1 id="snl_show에-출연한-celeb을-기준으로-두-테이블을-조인하여">snl_show에 출연한 celeb을 기준으로 두 테이블을 조인하여</h1>
<h1 id="celeb-테이블은-c-snl_show-테이블은-s라는-별칭을-만들어서---타이핑-리소스-줄일-수-있음">celeb 테이블은 c, snl_show 테이블은 s라는 별칭을 만들어서  =&gt; 타이핑 리소스 줄일 수 있음</h1>
<h1 id="출연한-시즌과-에피소드-이름-직업-검색">출연한 시즌과 에피소드, 이름, 직업 검색</h1>
<p>mysql&gt; select s.season, s.episode, c.name, c.job_title
    -&gt; from celeb as c, snl_show as s
    -&gt; where c.name=s.host;
+--------+---------+-----------+-------------------------+
| season | episode | name      | job_title               |
+--------+---------+-----------+-------------------------+
|      8 |       7 | 강동원    | 영화배우, 텔런트        |
|      8 |       8 | 유재석    | MC, 개그맨              |
|      8 |       9 | 차승원    | 영화배우, 모델          |
|      8 |      10 | 이수현    | 가수                    |
+--------+---------+-----------+-------------------------+
4 rows in set (0.00 sec)</p>
<h1 id="snl_show에-출연한-celeb을-기준으로-두-테이블을-조인하여-다음-데이터-별칭-사용하여-검색">snl_show에 출연한 celeb을 기준으로 두 테이블을 조인하여 다음 데이터 별칭 사용하여 검색</h1>
<h1 id="방송정보-시즌-에피스드-방송일">방송정보: 시즌, 에피스드, 방송일</h1>
<h1 id="출연자정보-이름-직업">출연자정보: 이름, 직업</h1>
<p>mysql&gt; select concat(s.season, &#39;시즌-&#39;, s.episode, &#39;화(&#39;, s.broadcast_date,&#39;)&#39;) &#39;방송정보&#39;, 
    -&gt; concat(c.name,&#39;(&#39;,c.job_title,&#39;)&#39;) &#39;출연자정보&#39;
    -&gt; from celeb as c, snl_show as s 
    -&gt; where name=host;
+---------------------------+------------------------------------+
| 방송정보                  | 출연자정보                         |
+---------------------------+------------------------------------+
| 8시즌-7화(2020-09-05)     | 강동원(영화배우, 텔런트)           |
| 8시즌-8화(2020-09-12)     | 유재석(MC, 개그맨)                 |
| 8시즌-9화(2020-09-19)     | 차승원(영화배우, 모델)             |
| 8시즌-10화(2020-09-26)    | 이수현(가수)                       |
+---------------------------+------------------------------------+
4 rows in set (0.01 sec)</p>
<pre><code>### Distinct (유니크한 컬럼 값 추출)
- Distinct: 검색한 결과의 중복 제거
`SELECT DISTINCT col1, col2, ... FROM tablename;`
```sql
mysql&gt; select distinct agency from celeb;
+--------------------------+
| agency                   |
+--------------------------+
| EDAM엔터테인먼트         |
| 울림엔터테인먼트         |
| 나무엑터스               |
| YG엔터테인먼트           |
| 안테나                   |
+--------------------------+
5 rows in set (0.01 sec)</code></pre><h3 id="limit">Limit</h3>
<ul>
<li>Limit: 검색 결과를 정렬된 순으로 주어진 숫자만큼만 조회
<code>SELECT col1, col2, ... FROM tablename WHERE condition LIMIT number;</code>
```sql<h1 id="나이가-가장-적은-연예인-4명-검색">나이가 가장 적은 연예인 4명 검색</h1>
mysql&gt; select * from celeb order by age asc limit 4;</li>
<li>----+-----------+------------+------+------+-------------------+--------------------------+
| id | name      | birthday   | age  | sex  | job_title         | agency                   |</li>
<li>----+-----------+------------+------+------+-------------------+--------------------------+
|  7 | 이수현    | 1999-05-04 |   23 | F    | 가수              | YG엔터테인먼트           |
|  2 | 이미주    | 1994-09-23 |   28 | F    | 가수              | 울림엔터테인먼트         |
|  3 | 송강      | 1994-04-23 |   28 | M    | 텔런트            | 나무엑터스               |
|  1 | 아이유    | 1993-05-16 |   29 | F    | 가수, 텔런트      | EDAM엔터테인먼트         |</li>
<li>----+-----------+------------+------+------+-------------------+--------------------------+
4 rows in set (0.00 sec)<pre><code></code></pre></li>
</ul>
<hr>
<h4 id="실습-문제">실습 문제</h4>
<pre><code class="language-sql"># 이름이 3글자인 연예인 정보 검색
mysql&gt; select concat(&#39;이름: &#39;, name, &#39;,  소속사: &#39;,agency) &#39;연예인 정보&#39; from celeb where name like &#39;___&#39;;
+--------------------------------------------------------+
| 연예인 정보                                            |
+--------------------------------------------------------+
| 이름: 아이유, 소속사: EDAM엔터테인먼트                 |
| 이름: 이미주, 소속사: 울림엔터테인먼트                 |
| 이름: 강동원, 소속사: YG엔터테인먼트                   |
| 이름: 유재석, 소속사: 안테나                           |
| 이름: 차승원, 소속사: YG엔터테인먼트                   |
| 이름: 이수현, 소속사: YG엔터테인먼트                   |
+--------------------------------------------------------+
6 rows in set (0.00 sec)

mysql&gt; select c.agency as &#39;소속사 정보&#39;, concat(&#39;나이: &#39;, c.age, &#39;(&#39;, c.sex, &#39;)&#39;) as &#39;신상정보&#39;, concat(s.season, &#39;시즌-&#39;, s.episode, &#39;방송날짜: &#39;, s.broadcast_date) as &#39;출연정보&#39; from celeb c, snl_show s  where c.name=s.host and c.agency like &#39;__ 엔터테인먼트&#39; order by s.broadcast_date desc;
+----------------------+---------------+------------------------------------+
| 소속사 정보          | 신상정보      | 출연정보                           |
+----------------------+---------------+------------------------------------+
| YG엔터테인먼트       | 나이: 23(F)   | 8시즌-10방송날짜: 2020-09-26       |
| YG엔터테인먼트       | 나이: 48(M)   | 8시즌-9방송날짜: 2020-09-19        |
| YG엔터테인먼트       | 나이: 41(M)   | 8시즌-7방송날짜: 2020-09-05        |
+----------------------+---------------+------------------------------------+
3 rows in set (0.00 sec)

# snl에 출연한 연예인의 정보를 나이 순으로 2개만 검색하여 출력
mysql&gt; select concat(&#39;SNL 시즌&#39;, s.season, &#39; 에피소드&#39;, s.episode, &#39; 호스트  &#39;, s.host) &#39;SNL 방송정보&#39;, c.age from celeb c, snl_show s where c.name=s.host order by c.age desc limit 2;
+------------------------------------------------+------+
| SNL 방송정보                                   | age  |
+------------------------------------------------+------+
| SNL 시즌8 에피소드8 호스트  유재석             |   50 |
| SNL 시즌8 에피소드9 호스트  차승원             |   48 |
+------------------------------------------------+------+
2 rows in set (0.00 sec)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[MySQL 설치 및 실행, Database 정의, SQL 구성]]></title>
            <link>https://velog.io/@sss_yeonii/MySQL-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%8B%A4%ED%96%89-Database-%EC%A0%95%EC%9D%98-SQL-%EA%B5%AC%EC%84%B1</link>
            <guid>https://velog.io/@sss_yeonii/MySQL-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%8B%A4%ED%96%89-Database-%EC%A0%95%EC%9D%98-SQL-%EA%B5%AC%EC%84%B1</guid>
            <pubDate>Sat, 27 Jul 2024 06:40:45 GMT</pubDate>
            <description><![CDATA[<h2 id="mysql-설치">MySQL 설치</h2>
<p>1) MySQL 다운로드: <a href="https://dev.mysql.com/downloads/mysql/">https://dev.mysql.com/downloads/mysql/</a>
2) 설치 프로그램 실행</p>
<ul>
<li>이때 설정한 Root Password는 찾을 수 있는 방법이 없기 때문에 잘 저장해두고 꼭 기억해야 한다</li>
</ul>
<h2 id="mysql-실행">MySQL 실행</h2>
<p>방법1. 터미널 활용해서 실행</p>
<pre><code>cd /usr/local/mysql/bin
./mysql -u root -p
Enter password: Root Password
mysql&gt; =&gt; 나오면 성공</code></pre><p>방법2. 매번 실행경로로 이동하여 실행시키기 귀찮다면 환경 변수 설정하기</p>
<p>1) 터미널 실행해서 아래 코드 입력</p>
<pre><code>sudo nano /etc/paths
Password: 컴퓨터 로그인 계정 PW 입력</code></pre><p>sudo: 관리자 권한으로 실행하겠다
nano: 파일 편집툴인 nano로 편집하겠다
/etc 하위 /paths를 편집하겠다
2) 가장 하위에 /usr/local/mysql/bin 추가 &gt; Control+X &gt; 저장? Y &gt; 엔터
3) 이제 터미널 실행 시, 바로 mysql 접근 가능!</p>
<pre><code>mysql -u root -p</code></pre><h2 id="mysql-workbench-설치하기">MySQL Workbench 설치하기</h2>
<p>1) <a href="https://dev.mysql.com/downloads/workbench/">https://dev.mysql.com/downloads/workbench/</a> 에서 다운로드
2) 설치 프로그램 실행하여 설치
3) 응용프로그램에서 MySQL Workbench 실행
4) 위 root password 설정하여 만든 Local Instance 3306 연결
5) root 계정으로 접속하기 위한 비밀번호 입력
참고) show databases 입력해서 번개 표시 클릭하면 실행됨. 컴퓨터에 있는 databases를 보여줌.
<img src="https://velog.velcdn.com/images/sss_yeonii/post/94b67966-1d8e-4c5f-8283-d93f72aae3a2/image.png" alt=""></p>
<h2 id="database-정의">Database 정의</h2>
<ul>
<li>Database: 여러 사람이 공유하여 사용할 목적으로 체계화해 통합, 관리하는 데이터의 집합체</li>
<li>DBMS(Database Management System): 사용자와 데이터베이스 사이에서 사용자의 요구에 따라 정보를 생성해주고 데이터베이스를 관리해주는 소프트웨어 (= MySQL)</li>
<li>관계형 데이터베이스(RDB: Relational Database): 서로 간에 관계가 있는 데이터 테이블들을 모아둔 데이터 저장공간 (= MySQL)</li>
<li>SQL(Structured Query Language): 데이터베이스에서 데이터를 정의, 조작, 제어하기 위해 사용하는 언어<h2 id="sql-구성">SQL 구성</h2>
</li>
<li>데이터 정의 언어(DDL: Data Definition Language)<ul>
<li>CREATE, ALTER, DROP 등 명령어</li>
</ul>
</li>
<li>데이터 조작 언어(DML: Data Manipulation Language)<ul>
<li>INSERT, UPDATE, DELETE, SELECT 등 명령어</li>
</ul>
</li>
<li>데이터 제어 언어(DCL: Data Control Language)<ul>
<li>GRANT, REVOKE, COMMIT, ROLLBACK 등 명령어</li>
</ul>
</li>
</ul>
<h4 id="단축키">단축키</h4>
<ul>
<li>코드 새로고침: control + C</li>
<li>터미널 창 새로고침(새창): system clear 입력</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[EDA] Selenium(셀레니움)]]></title>
            <link>https://velog.io/@sss_yeonii/EDA-Selenium%EC%85%80%EB%A0%88%EB%8B%88%EC%9B%80</link>
            <guid>https://velog.io/@sss_yeonii/EDA-Selenium%EC%85%80%EB%A0%88%EB%8B%88%EC%9B%80</guid>
            <pubDate>Sun, 14 Jul 2024 17:56:39 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p>Beautiful Soup만으로 해결할 수 없는 것 =&gt; Selenium 사용</p>
<ul>
<li>접근할 웹주소를 알 수 없을 때</li>
<li>자바스크립트를 사용하는 웹페이지의 경우</li>
<li>웹 브라우저로 접근하지 않으면 안될 때 <h1 id="selenium">Selenium</h1>
</li>
</ul>
</li>
<li><p>웹 브라우저를 원격 조작하는 도구</p>
</li>
<li><p>자동으로 URL 열고 클릭 등 가능</p>
</li>
<li><p>스크롤, 문자의 입력, 화면 캡처 등</p>
<h2 id="selenium-설치">selenium 설치</h2>
</li>
<li><p>모듈 설치: pip install selenium</p>
</li>
<li><p>webdriver 사용(<a href="https://www.selenium.dev/documentation/webdriver/">공식 문서</a>): 크롬 드라이버 설치 (크롬 버전 확인 필요)
=&gt; 를 하려고 했으나 셀레니움이 업데이트 되어서 이제 크롬 드라이버를 다운받지 않아도 된다고 함!!!!</p>
<ul>
<li><code>from selenium import webdriver</code>
<code>webdriver.Chrome()</code> 로만 실행해도 됨!</li>
<li>webdriver는 특정 브라우저에서 동작하는지를 테스트하기 위한 용도인데, selenium에서 웹크롤링할 때 사용하기 위해 불러옴. </li>
<li><code>webdriver.Chrome()</code>은 여러 브라우저 중 크롬이라는 브라우저에서 특정 웹페이지를 실행하겠다는 뜻임.<h2 id="selenium-기초">selenium 기초</h2>
</li>
</ul>
</li>
<li><p>get명령: 접근하고 싶은 주소 지정</p>
<ul>
<li><code>driver.get(&quot;https://www.naver.com&quot;)</code></li>
<li>크롬에서 새로운 페이지가 열림</li>
<li><code>driver.quit()</code> 으로 꼭 닫아줘야 함. 안그러면 크롬 결과가 여러 개 열려있을 수 있음. </li>
</ul>
</li>
<li><p>스크롤 가능한 높이 가져오기</p>
</li>
<li><p>xpath</p>
<ul>
<li>개발자 도구 사용해서 Copy Xpath</li>
</ul>
</li>
<li><p>정보 입력하기 </p>
</li>
<li><p>버튼 클릭</p>
</li>
<li><p>웹페이지의 팝업창 변환하는 명령: <code>driver.switch_to_window()</code></p>
</li>
<li><p>Action Chains: <a href="https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.action_chains">https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.action_chains</a></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[EDA] Web Data 분석하기 (Beautiful Soup)]]></title>
            <link>https://velog.io/@sss_yeonii/EDA-Web-Data-%EB%B6%84%EC%84%9D%ED%95%98%EA%B8%B0-Beautiful-Soup</link>
            <guid>https://velog.io/@sss_yeonii/EDA-Web-Data-%EB%B6%84%EC%84%9D%ED%95%98%EA%B8%B0-Beautiful-Soup</guid>
            <pubDate>Sun, 14 Jul 2024 09:35:24 GMT</pubDate>
            <description><![CDATA[<h2 id="beautiful-soup-공식-문서">[Beautiful Soup (<a href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/">공식 문서</a>)]</h2>
<h3 id="html-문법">HTML 문법</h3>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;Very Simple HTML Code by SY&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;div&gt;
            &lt;p clases = &quot;inner-text first-item&quot; id=&quot;first&quot;&gt;
                Happy Zerobase.
                &lt;a href=&quot;http://www.pinkwink.kr&quot; id=&quot;pw-link&quot;&gt;PinkWink&lt;/a&gt;
            &lt;/p&gt;
            &lt;p class=&quot;inner-text second-item&quot;&gt;
                Happy Data Science.
                &lt;a href=&quot;https://www.python.org&quot; target=&quot;_blink&quot; id=&quot;py-link&quot;&gt;Python&lt;/a&gt;
            &lt;/p&gt;
        &lt;/div&gt;
        &lt;p class=&quot;outer-text first-item&quot; id=&quot;second&quot;&gt;
            &lt;b&gt;Data Science is funny.&lt;/b&gt;
        &lt;/p&gt;
        &lt;p class=&quot;outer-text&quot;&gt;
            &lt;i&gt;All I need is love.&lt;/i&gt;
        &lt;/p&gt;
    &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/47f27384-4804-40de-b63f-e5dcff59051f/image.png" alt=""></p>
<ul>
<li>&lt;태그&gt;를 열었으면 &lt;/태그&gt;로 꼭 닫아줘야 함.</li>
<li><code>&lt;head&gt;</code>: 상단 창바의 이름</li>
<li><code>&lt;body&gt;</code>: 실제 창 구성</li>
<li><code>&lt;a href=&quot;링크&quot; id=&quot;id값&quot;&gt;텍스트명&lt;/a&gt;</code>: 하이퍼링크 생성<ul>
<li><code>target=&quot;_blink&quot;</code>: 클릭해서 창을 열 때 새로운 창으로 열림</li>
</ul>
</li>
<li><code>&lt;b&gt;&lt;/b&gt;</code>: 볼드체</li>
<li><code>&lt;i&gt;&lt;/i&gt;</code>: 기울임체<h3 id="beautifulsoup-설치하기">BeautifulSoup 설치하기</h3>
<ul>
<li>conda install -c anaconda beautifulsoup4</li>
<li>pip install beautifulsoup4<h3 id="python에서-beautifulsoup-사용해-html-읽기">Python에서 BeautifulSoup 사용해 HTML 읽기</h3>
1) <code>from bs4 import BeautifulSoup</code>
2) html 오픈해서 BeaufitulSoup으로 읽기<pre><code class="language-python">page = open(&quot;../data/03. zerobase.html&quot;, &quot;r&quot;).read()
soup = BeautifulSoup(page, &quot;html.parser&quot;)  
#page에 있는 내용을 BeautifulSoup으로 읽기
#Parser: https://www.crummy.com/software/BeautifulSoup/bs4/doc/ (어떤 엔진을 사용할지)
print(soup.prettify()) # html을 들여쓰기해서 좀 더 보기 편하게 만들기</code></pre>
<h3 id="beautifulsoup-태그-읽는-법">BeautifulSoup 태그 읽는 법</h3>
1) 간단한 방법</li>
</ul>
</li>
<li>soup.head</li>
<li>soup.body</li>
<li>soup.div</li>
<li>soup.p</li>
</ul>
<p>2) soup.find()</p>
<ul>
<li>가장 먼저 찾은 1개만 반환</li>
<li><code>soup.find(&quot;p&quot;)</code></li>
<li><code>soup.find(&quot;p&quot;, class_=&quot;inner-text second-item&quot;)</code><ul>
<li>class_: Python 예약어와 구분짓기 위해 &#39;_&#39; 사용</li>
</ul>
</li>
<li><code>soup.find(&quot;p&quot;, {&quot;class&quot;:&quot;outer-text first-item&quot;})</code><ul>
<li>dic형으로 불러올 p태그 지정</li>
</ul>
</li>
<li><code>soup.find(&quot;p&quot;, {&quot;class&quot;:&quot;outer-text first-item&quot;}).text.strip()</code> <ul>
<li>text만 불러오기. 이때 strip()으로 공백 지워주기.</li>
</ul>
</li>
<li><code>soup.find(&quot;p&quot;, {&quot;class&quot;:&quot;inner-text first-item&quot;, &quot;id&quot;: &quot;first&quot;})</code><ul>
<li>다중 조건 적용 가능</li>
</ul>
</li>
</ul>
<p>3) soup.find_all()</p>
<ul>
<li>여러 개의 태그를 리스트 타입으로 반환</li>
<li><code>soup.find_all(&quot;p&quot;)</code>: 모든 p태그 반환 </li>
<li><code>soup.find_all(class_=&quot;outer-text&quot;)</code>: 해당하는 2개의 p태그 불러옴</li>
<li><code>soup.find_all(id=&quot;pw-link&quot;)[0].text</code>: 리스트이기 때문에 [0]와 같이 인덱스 지정 필요</li>
</ul>
<p>4) p태그 리스트에서 텍스트 속성만 출력하기</p>
<ul>
<li><p><code>.text</code> / <code>.get_text()</code></p>
<pre><code class="language-python"># print와 함께 사용하면 예쁘게 출력됨
print(soup.find_all(&quot;p&quot;)[1].text)
print(soup.find_all(&quot;p&quot;)[1].get_text())
print(soup.find_all(&quot;p&quot;)[1].string)</code></pre>
<ul>
<li><p>for문으로 출력하기</p>
<pre><code class="language-python">for each_tag in soup.find_all(&quot;p&quot;):
print(&quot;=&quot;*50)
print(each_tag.text)
...
==================================================

           Happy Zerobase.
           PinkWink
</code></pre>
</li>
</ul>
</li>
</ul>
<p>==================================================</p>
<pre><code>            Happy Data Science.
            Python</code></pre><p>==================================================</p>
<p>Data Science is funny.</p>
<p>==================================================</p>
<p>All I need is love.</p>
<pre><code>5) a 태그에서 href 속성값에 있는 링크 추출
- `soup.find_all(&quot;a&quot;)[0].get(&quot;href&quot;)`
- `soup.find_all(&quot;a&quot;)[0][&quot;href&quot;]`
```python
links = soup.find_all(&quot;a&quot;)
links[0].get(&quot;href&quot;), links[1][&quot;href&quot;]
...
(&#39;http://www.pinkwink.kr&#39;, &#39;https://www.python.org&#39;)


for each in links:
    href = each.get(&quot;href&quot;) #혹은: each[&quot;href&quot;]
    text = each.get_text()
    print(text+&quot; -&gt; &quot;+href)</code></pre><hr>
<h3 id="1-네이버-금융-예제">1. 네이버 금융 예제</h3>
<h4 id="방법1-urlopen-import하여-네이버-금융-페이지의-html-읽기">방법1) urlopen import하여 네이버 금융 페이지의 html 읽기</h4>
<pre><code class="language-python">from urllib.request import urlopen 
from bs4 import BeautifulSoup

url = &quot;https://finance.naver.com/marketindex/&quot;
response = urlopen(url)
soup = BeautifulSoup(response, &quot;html.parser&quot;) 
print(soup.prettify())</code></pre>
<p>-<code>response.status</code>: URL 읽어주는 Request에 대한 HTTP 상태 코드</p>
<h4 id="방법2-requests-사용하기">방법2) requests 사용하기</h4>
<p>1) 터미널에서 requests 설치
<code>pip install requests</code>
<code>pip list | grep requests</code>: requests 설치되었는지, 버전과 함께 확인
2) VS Code에서 import</p>
<pre><code class="language-python">import requests # from urllib.request.Request 와 유사 =&gt; 편한 것 사용
from bs4 import BeautifulSoup</code></pre>
<p>3) 페이지 url 불러오기</p>
<pre><code class="language-python">url = &quot;https://finance.naver.com/marketindex/&quot;
response = requests.get(url) #requests.post() 방식도 있음.</code></pre>
<ul>
<li><code>response.text</code> / <code>response.content</code>: html 전체 출력</li>
<li><code>response</code>: request status 확인<ul>
<li>&lt;Response [200]&gt;로 성공 status가 출력됨</li>
</ul>
</li>
<li>들여쓰기 해서 예쁘게 보는 방법<pre><code class="language-python">soup = BeautifulSoup(response.text, &quot;html.parser&quot;)
print(soup.prettify())</code></pre>
<h4 id="네이버-금융-페이지의-환율과-국가-등-여러-정보-가져오기">네이버 금융 페이지의 환율과 국가 등 여러 정보 가져오기</h4>
</li>
<li>하나만 선택: find, select_one</li>
<li>여러 개 선택: select, find_all
=&gt; select가 class와 id를 아래와 같이 간단하게 불러올 수 있어서 편리함<ul>
<li>select에서 class는 앞에 &#39;.&#39;, id는 앞에 &#39;#&#39; 사용<pre><code class="language-python">exchangeList = soup.select(&quot;#exchangeList &gt; li&quot;)
# 즉, exchangeList라는 id를 가진 태그 중에서 하위에 li 태그 불러오기
</code></pre>
</li>
</ul>
</li>
</ul>
<p>title = exchangeList[0].select_one(&quot;.h_lst&quot;).text
exchange = exchangeList[0].select_one(&quot;.value&quot;).text
change = exchangeList[0].select_one(&quot;.change&quot;).text
updown = exchangeList[0].select_one(&quot;div.head_info.point_up &gt; .blind&quot;).text </p>
<h1 id="classhead_info-point_up와-같이-띄어쓰기-있을-때는-class가-2개인-것으로-인식함---select에서-불러올-때는-사이에-을-붙여줌">class=&quot;head_info point_up&quot;와 같이 띄어쓰기 있을 때는 class가 2개인 것으로 인식함 -&gt; select에서 불러올 때는 사이에 &#39;.&#39;을 붙여줌</h1>
<h1 id="의-의미-바로-하위에-있는-클래스의-값을-가져오는-것">&#39;&gt;&#39;의 의미: 바로 하위에 있는 클래스의 값을 가져오는 것</h1>
<p>baseUrl = &quot;<a href="https://finance.naver.com&quot;">https://finance.naver.com&quot;</a>
link = baseUrl + exchangeList[0].select_one(&quot;a&quot;).get(&quot;href&quot;)</p>
<p>title, exchange, change, updown, link</p>
<p>...
(&#39;미국 USD&#39;, &#39;1,377.00&#39;, &#39;3.50&#39;, &#39;상승&#39;, &#39;<a href="https://finance.naver.com/marketindex/exchangeDetail.naver?marketindexCd=FX_USDKRW&#39;">https://finance.naver.com/marketindex/exchangeDetail.naver?marketindexCd=FX_USDKRW&#39;</a>)</p>
<pre><code>
---

### 2. 위키백과 문서 불러오기 예제
#### URL 인코딩/디코딩하여 불러오는 방법
```python
from urllib.request import urlopen, Request
import urllib

html = &quot;https://ko.wikipedia.org/wiki/{search_words}&quot;
#https://ko.wikipedia.org/wiki/여명의_눈동자
req = Request(html.format(search_words=urllib.parse.quote(&quot;여명의_눈동자&quot;))) 
#글자를 URL로 인코딩  -&gt; 한글을 encoding/decoding해주는 사이트 사용하여 입력해도 됨.
response = urlopen(req)
soup = BeautifulSoup(response, &quot;html.parser&quot;)
print(soup.prettify())

# 출력하려는 텍스트값이 몇번째 줄에 존재하는지 확인하는 용도 (ul이 너무 많음!)
n=0
for each in soup.find_all(&quot;ul&quot;):
    print(&quot;=&gt;&quot; + str(n) + &quot;=========&quot;)
    print(each.get_text())
    n += 1
soup.find_all(&quot;ul&quot;)[35].text.strip().replace(&quot;\xa0&quot;, &quot;&quot;).replace(&quot;\n&quot;,&quot;&quot;)</code></pre><hr>
<h3 id="3-시카고-맛집-예제">3. 시카고 맛집 예제</h3>
<ul>
<li>Request 시, 403 에러: 웹페이지를 볼 수 있는 권한이 없어서 사이트에서 거절한 것! 
=&gt; user agent를 헤더에 넣는다<ul>
<li>1) 정석: 크롬 &gt; 개발자도구 &gt; 네트워크 &gt; 헤더 &gt; user-agent 확인
<code>req = Request(url, headers={&quot;user-agent&quot;: &quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36&quot;})</code></li>
<li>2) 간단한 방법: Chrome 넣는다
<code>req = Request(url, headers={&quot;User-Agent&quot;: &quot;Chrome&quot;})</code></li>
<li>3) fake user agent 사용<pre><code class="language-python">from fake_useragent import UserAgent
ua = UserAgent()
ua.ie  #Fake인 User Agent를 랜덤하게 반환함. 
req = Request(url, headers={&quot;user-agent&quot;: ua.ie})
#Fake로 받아온 user-agent를 입력해도 됨.</code></pre>
</li>
</ul>
</li>
<li>urljoin(절대주소, 상대주소) : 상대주소와 절대주소를 대응해줌.<ul>
<li>상대 주소에 절대주소가 이미 포함되어 있으면 상대주소만 반환되고, 없으면 절대주소가 붙어서 반환됨.</li>
<li><code>from urllib.parse import urljoin</code>
<code>url_add.append(urljoin(url_base, item.select_one(&quot;a&quot;).get(&quot;href&quot;)))</code></li>
</ul>
</li>
<li>type(tmp_one)와 같이 BeautifulSoup의 type을 확인할 수 있음 <ul>
<li>bs4.element.Tag</li>
</ul>
</li>
<li>Regular Expression (정규표현식) (<a href="https://docs.python.org/ko/3/library/re.html">공식 문서</a>)<ul>
<li><a href="https://wikidocs.net/4308">점프투파이썬 링크</a></li>
<li><code>import re</code></li>
<li>re.split(&quot;기준문자열&quot;, split할 텍스트) -&gt; 리스트형으로 split</li>
<li>re.search(&quot;$\d+.(\d+)?&quot;, price_address_tmp).group() -&gt; 정규표현식으로 찾은 값을 반환</li>
</ul>
</li>
<li>tqpm 라이브러리<ul>
<li>터미널에서 설치: conda install -c conda-forge tqdm</li>
<li>파이썬에서 반복 작업의 진행 상황을 시각적으로 보여주는 툴. tqdm을 사용하면 진행 상황을 실시간으로 확인할 수 있습니다. (출처: <a href="https://zephyrus1111.tistory.com/305">https://zephyrus1111.tistory.com/305</a>)</li>
</ul>
</li>
</ul>
<p>(참고)</p>
<ul>
<li><code>df.to_excel(&quot;./03. naverfinance.xlsx&quot;, encoding=&quot;utf-8&quot;)</code> 했을 때, 
<code>to_excel() got an unexpected keyword argument &#39;encoding&#39;</code> 에러 발생<ul>
<li>pandas.DataFrame.to_excel(<a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_excel.html">공식문서</a>)에서 encoding 옵션을 더이상 지원하지 않음.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[EDA] 서울시 CCTV, 범죄 현황 데이터 분석(matplotlib, pivot_table, Google Map API 사용하기, Python 모듈 설치)]]></title>
            <link>https://velog.io/@sss_yeonii/EDA</link>
            <guid>https://velog.io/@sss_yeonii/EDA</guid>
            <pubDate>Sat, 13 Jul 2024 07:45:55 GMT</pubDate>
            <description><![CDATA[<h3 id="참고-링크">참고 링크</h3>
<p><a href="https://matplotlib.org/stable/gallery/index">https://matplotlib.org/stable/gallery/index</a>
<a href="https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.plot.html">https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.plot.html</a></p>
<h3 id="matplotlib">matplotlib</h3>
<p>plt.show() 는 화면에 표시하는 기능을 하는데 Jupyter나 IPython을 사용할 때는 자동으로 표시되기 때문에 호출할 필요가 없다.</p>
<h3 id="python-모듈-설치">Python 모듈 설치</h3>
<ol>
<li>pip 명령</li>
</ol>
<ul>
<li>python의 공식 모듈 관리자</li>
<li><code>!pip list</code>: 현재 설치된 모듈 리스트 반환<ul>
<li>e.g. ds_study라는 콘다 환경 내에 설치된 모듈 리스트 반환</li>
</ul>
</li>
<li><code>!pip install module_name</code>: 모듈 설치</li>
<li><code>!pip uninstall module_name</code>: 설치된 모듈 제거</li>
<li>Jupyter에서는 &quot;!&quot;를 쓰면 OS 레벨에서의 명령을 할 수 있음. 
다만, 바로 코드를 export해서 사용하는 경우에는 &quot;!&quot;를 쓰면 에러가 나는 경우도 있어서 <code>get_ipython().system(&quot;pip list&quot;)</code> 를 쓰기도 함.</li>
</ul>
<ol start="2">
<li>conda 명령</li>
</ol>
<ul>
<li>pip를 사용하면 conda 환경에서 dependency 관리가 정확하지 않을 수 있다. 아나콘다에서는 가급적 conda 명령으로 모듈을 관리하는 것이 좋다.</li>
<li><code>conda list</code>: 설치된 모듈 list</li>
<li><code>conda install module_name</code>: 모듈 설치</li>
<li><code>condat uninstall module_name</code>: 모듈 제거</li>
<li><code>conda install -c channel_name module_name</code>: 지정된 배포 채널에서 모듈 설치  =&gt; 채널이 존재한다는 것이 차이점. </li>
<li>그러나 모든 모듈이 conda로 설치되는 것은 아니다</li>
</ul>
<h3 id="pandas-for-반복문-iterrows">pandas For 반복문: iterrows()</h3>
<pre><code>for idx, rows in df.iterros()</code></pre><ul>
<li>pandas 데이터 프레임은 대부분 2차원</li>
<li>이럴 때 for문을 사용하면 n번째라는 지정을 반복해서 가독률이 떨어짐</li>
<li>pandas 데이터 프레임은 반복문을 만들 때 iterrows()라는 옵션을 사용하면 편함.</li>
<li>받을 때, 인덱스와 내용으로 나누어 받는 것만 주의</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[EDA] Pandas 기초: 데이터 읽기, Series와 Data Frame, 데이터 정렬/선택/추가/삭제, apply()]]></title>
            <link>https://velog.io/@sss_yeonii/EDA-Pandas-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@sss_yeonii/EDA-Pandas-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Sat, 06 Jul 2024 16:14:12 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>제로 베이스: 서울시 CCTV 현황 데이터 분석</p>
</blockquote>
<h2 id="1-pandas로-csv-excel-파일-읽기">1. pandas로 csv, excel 파일 읽기</h2>
<pre><code class="language-python">import pandas as pd</code></pre>
<ul>
<li>원하는 모듈이 설치되어 있다면 import 명령으로 사용하겠다고 선언한다.</li>
<li>pandas 모듈을 부를건데, 이걸 pd라고 앞으로 부르겠다<pre><code class="language-python">from Module import function</code></pre>
</li>
<li>Module 안에 있는 function 하나만 부르고 싶다면 위와 같이 선언한다.</li>
</ul>
<pre><code class="language-python">CCTV_Seoul = pd.read_csv(
                &quot;../data/01. Seoul_CCTV.csv&quot;,
                endoding=&quot;utf-8&quot;
                  )</code></pre>
<ul>
<li>csv: comma separated values의 약자로, 콤마로 구분된 값들이라는 뜻!</li>
<li>csv는 띄어쓰기로 통상 구분되어서 그냥 read_csv 명령으로 읽기만 해도 된다. </li>
<li>긴 파일명을 끝까지 입력하지 말고 적당한 곳에서 TAB 키를 눌러보자 (근데 colab은 TAB이 동작 안함)</li>
<li>한글은 encoding 설정이 필수! </li>
</ul>
<p>&lt; pandas dataframe 구조 &gt;
<img src="https://velog.velcdn.com/images/sss_yeonii/post/f8401a8b-bdac-4b5c-a6a5-cdba7f91cade/image.png" alt=""></p>
<pre><code class="language-python"># column 이름 조회
CCTV_Seoul.columns 
CCTV_Seoul.columns[0]

# df.rename: column 이름 변경하기
# inplace =&gt; 실제로 데이터의 column 이름을 바꾸겠다, default가 False임.

# header=2: 위에서 2번 줄이 header라고 명시
# usecols= : 필요한 컬럼만 선택</code></pre>
<h2 id="2-data-frame-생성하기">2. Data Frame 생성하기</h2>
<ul>
<li><p>Pandas의 데이터형을 구성하는 기본은 Series: index와 value로 구성</p>
<ul>
<li><strong>한가지 데이터 타입만</strong> 가질 수 있음.</li>
<li>Seriese들이 여러 개 모인 것이 <strong>Data Frame</strong>!<ul>
<li>Series는 컬럼 한줄 한줄을 의미함<pre><code class="language-python">pd.Series([1,2,3,4]) #dtype: int64
pd.Series([1,2,3,4], dtype=np.float64) #dtype: float64
pd.Series([1,2,3,4], dtype=str) #dtype: object
pd.Series(np.array([1,2,3])) #dtype: int64
data = pd.Series([1,2,3,4, &quot;5&quot;]) #dtype: object</code></pre>
</li>
</ul>
</li>
</ul>
</li>
<li><p>날짜 데이터: <code>pd.date_range(&quot;날짜&quot;, periods=n)</code> 로 입력한 날짜로부터 n일 간의 날짜 생성</p>
<pre><code class="language-python"># 20240501부터 기준으로 6일간의 데이터가 생성됨.
dates = pd.date_range(&quot;20240501&quot;, periods=6)
dates
...
DatetimeIndex([&#39;2024-05-01&#39;, &#39;2024-05-02&#39;, &#39;2024-05-03&#39;, &#39;2024-05-04&#39;,
             &#39;2024-05-05&#39;, &#39;2024-05-06&#39;],
            dtype=&#39;datetime64[ns]&#39;, freq=&#39;D&#39;)</code></pre>
</li>
<li><p><code>pd.DataFrame()</code> : values, index, columns로 구성</p>
<pre><code class="language-python">import numpy as np
df = pd.DataFrame(
      np.random.randn(6,4),   
      # numpy 내장함수로 6행 4열(총 24개)의 랜덤요소 생성
      index=dates, 
      columns=[&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;]
  )</code></pre>
</li>
</ul>
<h2 id="3-데이터-훑어보기">3. 데이터 훑어보기</h2>
<h3 id="여러-간단한-기능">여러 간단한 기능</h3>
<pre><code class="language-python">df.head() #위에서부터 기본 5개, 숫자 지정도 가능
df.tail() #아래에서부터 기본 5개, 숫자 지정도 가능
df.index #index 가져오기
df.columns #columns 가져오기
df.values #values 가져오기
df.info() #데이터 프레임의 기본 정보 확인: 컬럼의 크기와 데이터 형태 확인
df.describe() #데이터 프레임의 기술 통계 정보 확인 (count, mean, std, min, max, 25%, 50%, 75%)</code></pre>
<h3 id="데이터-정렬">데이터 정렬</h3>
<ul>
<li><code>sort_values()</code>: 특정 컬럼(열)을 기준으로 데이터를 정렬한다.<ul>
<li>ascending=False 이면 내림차순 (True=오름차순이 디폴트)</li>
<li>inplace=Ture까지 해줘야 원본 데이터가 변경됨.<pre><code class="language-python">df.sort_values(by=&quot;B&quot;, ascending=False, inplace=True)</code></pre>
</li>
</ul>
</li>
</ul>
<h3 id="데이터-선택">데이터 선택</h3>
<h5 id="1-한-개-컬럼-선택">1) 한 개 컬럼 선택</h5>
<pre><code class="language-python">df[&quot;A&quot;]  #index와 A컬럼의 value 출력
type(df[&quot;A&quot;]) #pandas.core.series.Series
df.A #컬럼명이 알파벳이면 &#39;A&#39;로 아예 지정해서 불러올 수도 있음 (숫자X)</code></pre>
<h5 id="2-두-개-이상-컬럼-선택">2) 두 개 이상 컬럼 선택</h5>
<pre><code class="language-python"># 리스트 안에 리스트로 또 담아줘야 함
df[[&quot;A&quot;, &quot;B&quot;]]</code></pre>
<h5 id="3-offset-index">3) offset index</h5>
<ul>
<li><code>[n:m]</code>: n부터 m-1까지</li>
<li>인덱스나 컬럼의 이름으로 slice하는 경우는 끝(m)을 포함함<pre><code class="language-python">df[0:3]
# 1번째 행부터 3번째 행까지만 불러와짐
df[&quot;2024-05-01&quot;:&quot;2024-05-04&quot;]
# 1번째 행부터 4번째 행까지 불러와짐. 즉 끝이라고 지정한 행까지 불러와짐.</code></pre>
<h5 id="4-loc과-iloc">4) loc과 iloc</h5>
</li>
<li><code>loc[]</code>: location<ul>
<li>인덱스와 컬럼의 <strong>이름</strong>을 사용 가능<pre><code class="language-python">df.loc[:, [&quot;A&quot;, &quot;B&quot;]]
# 인덱스는 전부 다 가져오고, 컬럼은 A,B만 가져와라
df.loc[&quot;2024-05-01&quot;:&quot;2024-05-04&quot;, [&quot;A&quot;, &quot;D&quot;]]
#1번째 행부터 4번째 행까지, A와 D 컬럼만 불러와짐.
df.loc[&quot;2024-05-01&quot;:&quot;2024-05-04&quot;, &quot;A&quot;:&quot;D&quot;]
# 컬럼에서 offset index 활용해서 A부터 D까지 불러옴. 즉, D컬럼이 포함됨!</code></pre>
</li>
</ul>
</li>
<li><code>iloc[]</code>: integer location<ul>
<li>특정 행/컬럼의 <strong>순서(위치)</strong>를 기반으로 인덱싱 </li>
<li>컴퓨터가 인식하는 인덱스 값으로 선택<pre><code class="language-python">df.iloc[3] # 3번째 행의 데이터
df.iloc[3,2] #3번째 행, 2번째 컬럼의 데이터만 불러와짐
df.iloc[1:3, 1:3] # 1~2행, 1~2열만 불러와짐. 즉, 3번째 행과 3번째 열이 빠졌음.
df.iloc[:, 1:3] # 모든 행, 1~2컬럼만 불러옴.</code></pre>
<h5 id="5-condition-활용">5) condition 활용</h5>
</li>
</ul>
</li>
<li>df[condition]와 같이 사용하는 것이 일반적<pre><code class="language-python">df[df[&quot;A&quot;]&gt;0]
# 값이 0보다 큰 것만 불러오고, 0보다 작은 값의 자리에는 NaN(Not a Number, 데이터가 없다는 뜻)가 들어감.</code></pre>
<h3 id="데이터-추가수정">데이터 추가/수정</h3>
</li>
<li>기존 컬럼이 없으면 추가</li>
<li>기존 컬럼이 있으면 수정</li>
<li><code>isin()</code>: 특정 요소가 있는지 확인<pre><code class="language-python">df[&quot;E&quot;] = [&quot;one&quot;, &quot;two&quot;, &quot;three&quot;, &quot;four&quot;, &quot;five&quot;, &quot;six&quot;] # 컬럼 E를 추가
df[df[&quot;E&quot;].isin([&quot;two&quot;,&quot;five&quot;])] #E컬럼의 값이 two, five인 데이터 불러오기</code></pre>
<h3 id="특정-컬럼-제거">특정 컬럼 제거</h3>
</li>
<li><code>del</code> 삭제할 컬럼</li>
<li><code>drop(삭제할 컬럼, axis=)</code><ul>
<li>axix=0 가로, axis=1 세로<pre><code class="language-python">del df[&quot;E&quot;] #E컬럼 삭제
df.drop([&quot;D&quot;], axis=1) #D컬럼 삭제</code></pre>
</li>
</ul>
</li>
</ul>
<h3 id="apply함수">apply(함수)</h3>
<ul>
<li><code>apply(함수)</code> 데이터에 특정 함수를 적용시킴<pre><code class="language-python">df[&quot;A&quot;].apply(&quot;sum&quot;)
df[&quot;A&quot;].apply(&quot;mean&quot;)
df[&quot;A&quot;].apply(&quot;min&quot;), df[&quot;A&quot;].apply(&quot;max&quot;)
df.apply(np.sum) #전체 컬럼에 대한 sum
df[&quot;A&quot;].apply(np.cumsum) # A컬럼의 누적 합
</code></pre>
</li>
</ul>
<h1 id="직접-함수를-만들어보고-데이터-프레임에-적용해보기">직접 함수를 만들어보고 데이터 프레임에 적용해보기</h1>
<p>def plusminus(num):
    return &quot;plus&quot; if num &gt; 0 else &quot;minus&quot;</p>
<p>df[&quot;A&quot;].apply(plusminus)
...
2024-05-01    minus
2024-05-02    minus
2024-05-03     plus
2024-05-04    minus
2024-05-05    minus
2024-05-06     plus</p>
<pre><code>
## 4. 두 데이터 합치기

Pandas에서 데이터 프레임을 병합하는 방법 3가지
- pd.concat()
- pd.merge()
- pd.join()

### [ pd.merge() ]
- 두 데이터 프레임에서 컬럼이나 인덱스를 기준으로 잡고 병합하는 방법
- 기준이 되는 컬럼이나 인덱스를 키값이라고 함
- 기준이 되는 키값은 두 데이터 프레임에 모두 포함되어 있어야 함

#### 예시 데이터 프레임 만들기
![](https://velog.velcdn.com/images/sss_yeonii/post/60dd990c-7ecd-4b47-8710-9b41a8155c31/image.png)
```python
# 딕셔너리 안의 리스트 형태
left = pd.DataFrame({ # 컬럼의 값을 순서대로 나열
    &quot;key&quot;: [&quot;K0&quot;, &quot;K4&quot;, &quot;K2&quot;, &quot;K3&quot;],
    &quot;A&quot;: [&quot;A0&quot;, &quot;A1&quot;, &quot;A2&quot;, &quot;A3&quot;],
    &quot;B&quot;: [&quot;B0&quot;, &quot;B1&quot;, &quot;B2&quot;, &quot;B3&quot;]
})
# 리스트 안의 딕셔너리 형태: 행의 값을 순서대로 나열
right = pd.DataFrame([
    {&quot;key&quot;: &quot;K0&quot;, &quot;C&quot;:&quot;C0&quot;, &quot;D&quot;: &quot;D0&quot;},
    {&quot;key&quot;: &quot;K1&quot;, &quot;C&quot;:&quot;C1&quot;, &quot;D&quot;: &quot;D1&quot;},
    {&quot;key&quot;: &quot;K2&quot;, &quot;C&quot;:&quot;C2&quot;, &quot;D&quot;: &quot;D2&quot;},
    {&quot;key&quot;: &quot;K3&quot;, &quot;C&quot;:&quot;C3&quot;, &quot;D&quot;: &quot;D3&quot;},
])</code></pre><h4 id="pdmergeleft-right-on-how">pd.merge(left, right, on=&quot;&quot;, how=&quot;&quot;)</h4>
<ul>
<li>on: 기준이 되는 컬럼</li>
<li>how: merge하는 방법 (디폴트: inner라는 교집합)</li>
</ul>
<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/3c17b4c4-c1f5-485a-8344-85c9d62f0041/image.png" alt=""></p>
<pre><code class="language-python">pd.merge(left, right, on=&quot;key&quot;) 
# key 컬럼을 기준으로 left와 right 데이터 프레임을 합치겠다
# #how의 디폴트: inner -&gt; key 컬럼에서 공통으로 가지고 있는 값에 대해서만 합쳐짐</code></pre>
<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/71a7b6f1-c071-4d71-911b-433aea3b821a/image.png" alt=""></p>
<pre><code class="language-python">pd.merge(left, right, how=&quot;left&quot;, on=&quot;key&quot;)
# key 컬럼을 기준으로 left와 right 데이터 프레임을 합치겠다
# 하지만 left에 있는 값을 기준으로 합쳐라
# right에는 존재하지 않는 K4 행의 값이 NaN</code></pre>
<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/1eb7bf29-e7e1-4ec1-9af8-2c353bf18865/image.png" alt=""></p>
<pre><code class="language-python">pd.merge(left, right, how=&quot;right&quot;, on=&quot;key&quot;)
# key 컬럼을 기준으로 left와 right 데이터 프레임을 합치겠다
# 하지만 right에 있는 값을 기준으로 합쳐라  
# left에는 존재하지 않는 K1 행의 값이 NaN</code></pre>
<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/adfa92b6-952f-45fb-9a89-bbe86c9859d6/image.png" alt=""></p>
<pre><code class="language-python">pd.merge(left, right, how=&quot;outer&quot;, on=&quot;key&quot;)
# key 컬럼을 기준으로 left와 right 데이터 프레임을 합치겠다
# 하지만 outer인 합집합으로서, key에 있던 없던 다 합쳐라
# left에는 존재하지 않는 K1 행의 값이 NaN, right에는 존재하지 않는 K4 행의 값이 NaN</code></pre>
<h4 id="인덱스-변경-set_index">인덱스 변경 set_index()</h4>
<ul>
<li><code>set_index()</code>: 선택한 컬럼을 데이터 프레임의 인덱스로 지정<pre><code>data_result.set_index(&quot;구별&quot;, inplace=True)
data_result.head()</code></pre><img src="https://velog.velcdn.com/images/sss_yeonii/post/517ecf53-a70b-4bed-911e-7dc0b298630e/image.png" alt=""></li>
</ul>
<h3 id="상관계수-corr">상관계수 corr()</h3>
<ul>
<li>correlation의 약자</li>
<li>상관계수가 0.2 이상인 데이터를 비교</li>
<li>int, float 타입만 사용 가능 (object X)
<img src="https://velog.velcdn.com/images/sss_yeonii/post/49389c31-a462-442a-a2d5-2a6be4c8c9aa/image.png" alt=""></li>
</ul>
<h3 id="😇-pandas-문서-모음-문서를-찾아보는-습관-들이기">😇 pandas 문서 모음 (문서를 찾아보는 습관 들이기!)</h3>
<ol>
<li>pandas.read_csv: <a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html#pandas-read-csv">https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html#pandas-read-csv</a></li>
<li>pandas.DataFrame.rename: <a href="https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rename.html#pandas-dataframe-rename">https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rename.html#pandas-dataframe-rename</a></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[EDA 환경 설정] Miniconda, Homebrew, Jupyter / Visual Studio Code 설치와 단축키]]></title>
            <link>https://velog.io/@sss_yeonii/EDA-%ED%99%98%EA%B2%BD-%EC%84%A4%EC%A0%95</link>
            <guid>https://velog.io/@sss_yeonii/EDA-%ED%99%98%EA%B2%BD-%EC%84%A4%EC%A0%95</guid>
            <pubDate>Sat, 06 Jul 2024 14:28:51 GMT</pubDate>
            <description><![CDATA[<h3 id="1-miniconda-설치---miniforge">1. Miniconda 설치 -&gt; Miniforge</h3>
<ul>
<li>아나콘다 사용도 가능하지만, miniconda를 설치하여 필요한 패키지만 따로 설치해줄 수도 있음.</li>
<li>수업은 Python 3.8 기준으로 진행할 예정</li>
</ul>
<ol>
<li>miniforge로 이동해서 M1용 다운로드: <a href="https://github.com/conda-forge/miniforge?tab=readme-ov-file">https://github.com/conda-forge/miniforge?tab=readme-ov-file</a></li>
<li>터미널 실행</li>
<li>cd Downloads 로 Downloads 폴더 열기</li>
<li>ls Mini(탭하여 자동 완성)forge3-MacOSX-arm64.sh 입력 후 설치 진행<ul>
<li>이때 ls Mini에서 탭하여 자동 완성</li>
</ul>
</li>
<li>yes 두번 입력</li>
<li>설치가 완료됐으면 터미널 종료 후 다시 켜기</li>
<li>(base)가 좌측에 있으면 설치 완료된 것!</li>
</ol>
<h3 id="2-homebrew-설치">2. Homebrew 설치</h3>
<ol>
<li><a href="https://brew.sh/">https://brew.sh/</a> 사이트에서 코드 복사 </li>
<li>터미널 앱 실행하여 코드 붙여넣기</li>
<li>맥북 패스워드 입력 (아무것도 입력 안되는 것처럼 보이는 게 정상)</li>
<li>설치 중 파일 경로를 변경해주는 echo, eval 코드를 그대로 입력</li>
<li>brew help 가 검색되면 잘 설치한 것!</li>
</ol>
<hr>
<p>&lt;강의 환경 만들기&gt;</p>
<p>1) conda --version  : conda 버전 확인
     - conda update conda로 버전 업데이트 가능
2) conda create -n ds_study python=3.8  -&gt; y입력
     - 강의 환경과 동일하게 맞추기 위해 python=3.8로 설정
3) conda activate ds_study  -&gt; (base)가 (ds_study)로 변경된 것을 확인할 수 있음
     - (base)로 빠져나오고 싶다면: conda deactivate 입력
     - conda env list : 현재 컴퓨터에 있는 환경이 무엇이 있는지를 확인할 수 있음
     - 특정 환경 삭제: conda env remove -n (삭제하고 싶은 환경 이름)</p>
<p>=&gt; 앞으로 강의할 때마다 conda activate ds_study로 환경 활성화해두기!</p>
<h3 id="3-jupyter와-여러-패키지-설치">3. Jupyter와 여러 패키지 설치</h3>
<pre><code>conda install jupyter
conda install ipython
conda install matplotlib
conda install seaborn
conda install pandas
conda install -y scikit-learn   #-y로 y입력하지 않고 설치할 수 있음
conda install xlrd
(ds_study)가 활성화되어있는지 확인한 후, jupyter notebook 실행</code></pre><h3 id="3-visual-studio-code-설치">3. Visual Studio Code 설치</h3>
<ol>
<li>터미널 실행</li>
<li>brew install visual-studio-code</li>
<li>code 입력하여 Visual Studio Code 실행</li>
<li>Visual Studio Code에서 ..
1) Python Extension 설치
2) 문서 &gt; 새파일 &gt; test.py / test.ipynb 생성 해보기
3) cmd+shift+p -&gt; python select interpreter 입력 -&gt; conda에서 생성했던 ds_study 환경 선택
4) test.ipynb 는 Jupyter notebook을 vsc에서 생성한 것</li>
</ol>
<ul>
<li>동일하게 ds_study 환경 선택</li>
</ul>
<hr>
<h3 id="visual-studio-code-사용하는-방법">Visual Studio Code 사용하는 방법</h3>
<ol>
<li>terminal 실행</li>
<li>cd Documents/ds_study   #문서 내 ds_study 열기</li>
<li>code .  # 현재 폴더인 ds_study에서 vscode 열겠다는 뜻</li>
</ol>
<blockquote>
<p>참고) cd ..  # Documnets로 이동하겠다는 뜻 
=&gt; . (온점 한 개): 현재 폴더를 의미
-&gt; ..  (온점 두 개): 상위 폴더를 의미</p>
</blockquote>
<ol start="4">
<li>Visual Studio Code가 실행됨</li>
<li>새로운 파일 생성: .ipynb로 확장자명을 필수로 설정해 주어야 주피터 노트북 환경이 실행됨.</li>
<li>cmp+shift+p (윈도우: ctrl) 검색창에서 Python Select interpreter를 눌러서 ds_study 선택</li>
</ol>
<hr>
<h3 id="🧡-visual-studio-code-단축키-🧡">🧡 Visual Studio Code 단축키 🧡</h3>
<blockquote>
<p><code>셀 선택모드</code>와 <code>코드 입력 모드</code> 의 전환은 <code>ESC</code>와 <code>Enter</code></p>
</blockquote>
<h4 id="공통">공통</h4>
<ul>
<li><code>Ctrl + Enter</code> : 현재 셀을 실행하고, 현재 셀에 머문다.</li>
<li><code>Shift + Enter</code> : 현재 셀을 실행하고, 다음 셀로 커서를 옮긴다 (다음 셀이 없다면 생성함)<h4 id="셀-선택-모드">셀 선택 모드</h4>
</li>
<li><code>A</code> : 현재 셀에서 위쪽에 새로운 셀을 추가한다.</li>
<li><code>B</code> : 현재 셀에서 아래쪽에 새로운 셀을 추가한다.</li>
<li><code>DD</code> : 현재 셀을 삭제한다.</li>
<li><code>M</code> : 현재 셀을 코드에서 마크다운으로 변경한다.</li>
<li><code>Y</code> : 현재 셀을 마크다운에서 코드로 변경한다.</li>
</ul>
<h4 id="코드-입력모드">코드 입력모드</h4>
<ul>
<li>Ctrl + Z, Ctrl + F 등 VS Code가 코드 입력 시 지원하는 대부분의 단축키를 쓸 수 있다.</li>
</ul>
<h3 id="유용한-맥북-단축키">유용한 맥북 단축키</h3>
<ul>
<li>백틱(`)<ul>
<li>영어 모드: ₩를 누르면 `가 입력된다.</li>
<li>한글 모드(option+₩): 디폴트로 ₩가 입력된다. 단, option과 함께 누르면 `를 입력할 수 있다. </li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 선형 검색, 이진 검색, 순위, 버블/삽입/선택/병합/퀵 정렬, 최댓값/최솟값/최빈값/근삿값/평균, 재귀, 하노이의탑]]></title>
            <link>https://velog.io/@sss_yeonii/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%84%A0%ED%98%95-%EA%B2%80%EC%83%89-%EC%9D%B4%EC%A7%84-%EA%B2%80%EC%83%89-%EC%88%9C%EC%9C%84-%EB%B2%84%EB%B8%94-%EC%A0%95%EB%A0%AC-%EC%82%BD%EC%9E%85-%EC%A0%95%EB%A0%AC-%EC%84%A0%ED%83%9D-%EC%A0%95%EB%A0%AC</link>
            <guid>https://velog.io/@sss_yeonii/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%84%A0%ED%98%95-%EA%B2%80%EC%83%89-%EC%9D%B4%EC%A7%84-%EA%B2%80%EC%83%89-%EC%88%9C%EC%9C%84-%EB%B2%84%EB%B8%94-%EC%A0%95%EB%A0%AC-%EC%82%BD%EC%9E%85-%EC%A0%95%EB%A0%AC-%EC%84%A0%ED%83%9D-%EC%A0%95%EB%A0%AC</guid>
            <pubDate>Tue, 25 Jun 2024 16:05:01 GMT</pubDate>
            <description><![CDATA[<h2 id="선형-검색">선형 검색</h2>
<ul>
<li>일렬로 나열되어 있는 데이터를 순차적으로 스캔하면서 원하는 값을 찾는다</li>
<li>인데스 0부터 9까지 순차적으로 검색 -&gt; 검색 성공 or 검색 실패<pre><code class="language-python">datas = [3,2,5,7,9,1,2,4,3,8]
print(f&#39;datas: {datas}&#39;)
</code></pre>
</li>
</ul>
<p>searchData = int(input(&#39;찾으려는 숫자 입력: &#39;))
searchResultIdx = -1 #존재하지 않는 인덱스를 주기 위함</p>
<p>n=0
while True:
    if n == len(datas):  #datas 길이 끝까지 갔는데 데이터가 없을 때
        print(&#39;찾으려는 데이터가 존재하지 않습니다.&#39;)
        break
    elif datas[n] == searchData:
        searchResultIdx = n
        break
    n += 1</p>
<p>print(f&#39;searchResultIdx: {searchResultIdx}&#39;)</p>
<p>...
datas: [3, 2, 5, 7, 9, 1, 2, 4, 3, 8]
찾으려는 숫자 입력: 8
searchResultIdx: 9</p>
<pre><code>### 보초법
- 마지막 인덱스에 찾으려는 값을 추가해서 찾는 과정을 간략화한다
- 인덱스 0부터 10까지 순차적으로 검색(10번째에 9 임의로 추가) -&gt; 9 검색 -&gt; 검색 성공: 마지막 이전에 9가 검색된 경우 / 검색 실패: 마지막에 9가 검색된 경우
```python
datas = [4,7,10,2,4,7,0,2,7,3,9]
print(f&#39;datas: {datas}&#39;)

searchData = 7
searchResultIdx = -1 #존재하지 않는 인덱스를 주기 위함
sumData = 0
n=0
while True:
    if n == len(datas):
        break

    elif datas[n] == searchData:
        print(f&#39;7의 위치(인덱스): {n}&#39;)
        sumData += 1

    n += 1
print(f&#39;7의 개수: {sumData}&#39;)

...
datas: [4, 7, 10, 2, 4, 7, 0, 2, 7, 3, 9]
7의 위치(인덱스): 1
7의 위치(인덱스): 5
7의 위치(인덱스): 8
7의 개수: 3</code></pre><p>&lt;파이썬 실습&gt;</p>
<ul>
<li>datas에서 7의 위치와 몇 개가 존재하는지 출력하는 프로그램을 생성해보세요.<pre><code class="language-python">datas = [4,7,10,2,4,7,0,2,7,3,9]
</code></pre>
</li>
</ul>
<p>searchData = int(input(&#39;검색할 숫자 입력: &#39;))
datas.append(searchData)  #보초법으로 마지막에 검색할 숫자 넣기
searchResultIdx = []</p>
<p>n=0
while True:
    if datas[n] == searchData:
        if n != len(datas) - 1: #보초법에 의해 추가된 숫자라면 제외
            searchResultIdx.append(n)
        else:
            break
    n += 1</p>
<p>print(f&#39;datas: {datas}&#39;)
print(f&#39;searchResultIdx: {searchResultIdx}&#39;)
print(f&#39;검색할 숫자 {searchData}의 총 개수: {len(searchResultIdx)}&#39;)
...
검색할 숫자 입력: 7
datas: [4, 7, 10, 2, 4, 7, 0, 2, 7, 3, 9, 7]
searchResultIdx: [1, 5, 8]
검색할 숫자 7의 총 개수: 3</p>
<pre><code>- 숫자로 이루어진 리스트에서 사용자가 입력한 숫자를 검색하는 모듈으르 다음 요건에 따라 만들어보자.
![](https://velog.velcdn.com/images/sss_yeonii/post/6c198345-99a3-4468-9693-a2f8a268d7fb/image.png)
```python
def searchNumberByLineAlgorithm(ns, sn):

    searchResultIdx = -1

    print(f&#39;Numbers: {ns}&#39;)
    print(f&#39;Search Number: {sn}&#39;)

    n=0
    while True:
        if n == len(ns): #찾다가 끝까지 온 것이면 Fail
            print(&#39;Search Fail&#39;)
            break

        if ns[n] == sn:
            searchResultIdx = n
            print(&#39;Search Success&#39;)
            print(f&#39;Search result Index: {searchResultIdx}&#39;)
            break
        n += 1

    return searchResultIdx

------실행파일------
import lineMod
import random

if __name__ == &#39;__main__&#39;:
    rNums = random.sample(range(1,21), 10)
    searchNum = int(input(&#39;input search number: &#39;))

    resultIdx = lineMod.searchNumberByLineAlgorithm(rNums, searchNum)
    if resultIdx == -1:
        print(&#39;No result found&#39;)
        print(f&#39;resultIdx: {resultIdx}&#39;)
    else:
        print(&#39;&gt;&gt;&gt; Search Results &lt;&lt;&lt;&#39;)
        print(f&#39;resultIdx: {resultIdx}&#39;)
        print(f&#39;result number: {rNums[resultIdx]}&#39;)

....
input search number: 8
Numbers: [9, 14, 12, 13, 18, 8, 6, 10, 17, 2]
Search Number: 8
Search Success
Search result Index: 5
&gt;&gt;&gt; Search Results &lt;&lt;&lt;
resultIdx: 5
result number: 8</code></pre><h2 id="이진-검색">이진 검색</h2>
<ul>
<li>이진 검색: <strong>정렬되어 있는</strong> 자료 구조에서 중앙값과의 크고 작음을 이용해서 검색 범위를 좁혀나가면서 데이터를 검색한다.
<img src="https://velog.velcdn.com/images/sss_yeonii/post/274c59db-0c95-4f05-a73e-ffc3ec80b222/image.png" alt=""></li>
<li>정렬되어 있어야 하기 때문에 sort() 함수 활용<pre><code class="language-python">datas = [1,2,3,4,5,6,7,8,9,10,11]
</code></pre>
</li>
</ul>
<p>startIdx = 0
endIdx = len(datas) - 1
midIdx = (startIdx+endIdx) // 2 #시작+끝 인덱스 나누기 2의 몫
midVal = datas[midIdx]</p>
<p>searchData = int(input(&#39;검색할 숫자 입력: &#39;))
searchDataIdx = -1</p>
<p>while searchData in datas:</p>
<pre><code>if searchData == midVal:
    searchDataIdx = midIdx
    break

elif searchData == datas[len(datas) - 1]:
    searchDataIdx = len(datas) - 1
    break

elif searchData &gt; midVal:
    startIdx = midIdx
    midIdx = (startIdx+endIdx) // 2
    midVal = datas[midIdx]
    print(f&#39;midIdx: {midIdx}&#39;)
    print(f&#39;midVal: {midVal}&#39;)

elif searchData &lt; midVal:
    endIdx = midVal
    midIdx = (startIdx+endIdx) // 2
    midVal = datas[midVal]
    print(f&#39;midIdx: {midIdx}&#39;)
    print(f&#39;midVal: {midVal}&#39;)</code></pre><p>print(f&#39;{searchData}의 위치 {searchDataIdx}&#39;)</p>
<p>...
검색할 숫자 입력: 10
midIdx: 7
midVal: 8
midIdx: 8
midVal: 9
midIdx: 9
midVal: 10
10의 위치 9</p>
<pre><code>
## 순위 
- 순위: 수의 크고 작음을 이용해서 수의 순위를 정하는 것
![](https://velog.velcdn.com/images/sss_yeonii/post/f4ac77e0-da57-466e-8083-5c06144f9c69/image.png)
&lt; 파이썬 실습&gt;
- 학급 학생(20명)들의 중간고사와 기말고사 성적을 이용해서 각각의 순위를
구하고, 중간고사 대비 기말고사 순위 변화(편차)를 출력하는 프로그램을
만들어 보자.(시험 성적은 난수를 이용한다.)
```python
class RandDeviation:

    def __init__(self, mss, ess):
        self.midStuScos = mss
        self.endStuScos = ess
        self.midRanks = [0 for i in range(len(mss))]
        self.endRanks = [0 for i in range(len(ess))]
        self.randDeviation = [0 for i in range(len(mss))]

    def setRank(self, ss, rs):
        for idx, score1 in enumerate(ss):
            for score2 in ss:
                if score1 &lt; score2:
                    rs[idx] += 1

    def setMidRank(self):
        self.setRank(self.midStuScos, self.midRanks)

    def getMidRank(self):
        return self.midRanks

    def setEndRank(self):
        self.setRank(self.endStuScos, self.endRanks)

    def getEndRank(self):
        return self.endRanks

    def printRankDeviation(self): #순위 변동 출력
        for idx, mRank in enumerate(self.midRanks):
            deviation = mRank - self.endRanks[idx]

            if deviation &gt; 0:
                deviation = &#39;↑&#39; + str(abs(deviation)) #절댓값

            elif deviation &lt; 0:
                deviation = &#39;↓&#39; + str(abs(deviation)) #절댓값

            else:
                deviation = &#39;=&#39; + str(abs(deviation))

            print(f&#39;midRank: {mRank}, \t endRank: {self.endRanks[idx]}, \t Deviation: {deviation}&#39;)

------ 실습 파일 ------
import rankMod
import random

midStuScos = random.sample(range(50, 101), 20)
endStuScos = random.sample(range(50, 101), 20)

rd = rankMod.RandDeviation(midStuScos, endStuScos)
rd.setMidRank()
print(f&#39;midStuScos: {midStuScos}&#39;)
print(f&#39;mid_rank: {rd.getMidRank()}&#39;)
rd.setEndRank()
rd.getEndRank()

print(f&#39;endStuScos: {endStuScos}&#39;)
print(f&#39;end_rank: {rd.getEndRank()}&#39;)

rd.printRankDeviation()

...
midStuScos: [98, 100, 94, 84, 93, 75, 77, 55, 80, 51, 56, 73, 52, 68, 65, 57, 60, 83, 66, 79]
mid_rank: [1, 0, 2, 4, 3, 9, 8, 17, 6, 19, 16, 10, 18, 11, 13, 15, 14, 5, 12, 7]
endStuScos: [89, 53, 74, 77, 72, 54, 71, 85, 98, 62, 68, 86, 58, 94, 76, 92, 52, 57, 91, 59]
end_rank: [4, 18, 9, 7, 10, 17, 11, 6, 0, 13, 12, 5, 15, 1, 8, 2, 19, 16, 3, 14]
midRank: 1,      endRank: 4,      Deviation: ↓3
midRank: 0,      endRank: 18,      Deviation: ↓18
midRank: 2,      endRank: 9,      Deviation: ↓7
midRank: 4,      endRank: 7,      Deviation: ↓3
midRank: 3,      endRank: 10,      Deviation: ↓7
midRank: 9,      endRank: 17,      Deviation: ↓8
midRank: 8,      endRank: 11,      Deviation: ↓3
midRank: 17,      endRank: 6,      Deviation: ↑11
midRank: 6,      endRank: 0,      Deviation: ↑6
midRank: 19,      endRank: 13,      Deviation: ↑6
midRank: 16,      endRank: 12,      Deviation: ↑4
midRank: 10,      endRank: 5,      Deviation: ↑5
midRank: 18,      endRank: 15,      Deviation: ↑3
midRank: 11,      endRank: 1,      Deviation: ↑10
midRank: 13,      endRank: 8,      Deviation: ↑5
midRank: 15,      endRank: 2,      Deviation: ↑13
midRank: 14,      endRank: 19,      Deviation: ↓5
midRank: 5,      endRank: 16,      Deviation: ↓11
midRank: 12,      endRank: 3,      Deviation: ↑9
midRank: 7,      endRank: 14,      Deviation: ↓7            </code></pre><ul>
<li>알파벳 문자들과 정수들에 대한 순위를 정하는 프로그램을 순위 알고리즘을 이용해서 만들어 보자. 단, 알파벳은 아스키코드 값을 이용한다.
[32, ‘a’, ‘z’, 45, ‘G’, 39, 50, ‘T’, ‘t’, 22, 31, 55, ‘s’, 63, 59, ‘E’]</li>
</ul>
<pre><code class="language-python">datas = [32, &#39;a&#39;, &#39;z&#39;, 45, &#39;G&#39;, 39, 50, &#39;T&#39;, &#39;t&#39;, 22, 31, 55, &#39;s&#39;, 63, 59, &#39;E&#39;]
print(f&#39;datas: {datas}&#39;)
ranks = [0 for i in range(len(datas))]

ascIIDatas = []

for data in datas:
    if str(data).isalpha(): #isalpha: 알파벳이냐 아니냐! 내가 썼던 코드: type(datas[i]) == type(&#39;data&#39;)
        ascIIDatas.append(ord(data))
    else:
        ascIIDatas.append(data)

print(f&#39;ascIIDatas: {ascIIDatas}&#39;)

for idx, data1 in enumerate(ascIIDatas):
    for data2 in ascIIDatas:
        if data1 &lt; data2:
            ranks[idx] += 1

print(f&#39;ranks: {ranks}&#39;)
for i, d in enumerate(ascIIDatas):
    print(f&#39;data: {d:&gt;2} \t rank: {(ranks[i]+1):&gt;2}&#39;)  #오른쪽정렬: &#39;:&gt;2&#39;

.....
datas: [32, &#39;a&#39;, &#39;z&#39;, 45, &#39;G&#39;, 39, 50, &#39;T&#39;, &#39;t&#39;, 22, 31, 55, &#39;s&#39;, 63, 59, &#39;E&#39;]
ascIIDatas: [32, 97, 122, 45, 71, 39, 50, 84, 116, 22, 31, 55, 115, 63, 59, 69]
ranks: [13, 3, 0, 11, 5, 12, 10, 4, 1, 15, 14, 9, 2, 7, 8, 6]
data: 32      rank: 14
data: 97      rank:  4
data: 122      rank:  1
data: 45      rank: 12
data: 71      rank:  6
data: 39      rank: 13
data: 50      rank: 11
data: 84      rank:  5
data: 116      rank:  2
data: 22      rank: 16
data: 31      rank: 15
data: 55      rank: 10
data: 115      rank:  3
data: 63      rank:  8
data: 59      rank:  9
data: 69      rank:  7</code></pre>
<h2 id="버블-정렬">버블 정렬</h2>
<ul>
<li><p>버블 정렬: 처음부터 끝까지 인접하는 인덱스의 값을 순차적으로 비교하면서 큰 숫자를 가장 끝으로 옮기는 알고리즘
<img src="https://velog.velcdn.com/images/sss_yeonii/post/dcb29019-c812-4d0c-a35b-0195e84d9840/image.png" alt="">
```python
def bubbleSort(ns, deepCopy=True):</p>
<p>  if deepCopy:  #깊은 복사</p>
<pre><code>  cns = copy.copy(ns)  #ns를 copy해서 cns라는 완전히 새로운 변수를 생성 =&gt; students는 그대로 유지 가능</code></pre><p>  else:</p>
<pre><code>  cns = ns  #얕은 복사</code></pre><p>  length = len(cns) - 1 #버블 정렬 시, 처음의 숫자를 마지막 앞의 숫자까지만 비교하면 되기 때문에 -1을 해줌.
  for i in range(length):</p>
<pre><code>  for j in range(length-i):
      if cns[j] &gt; cns[j+1]:  #비교하려는 ns[j]의 값 보다 그 다음의 값인 ns[j+1]이 더 크다면
          cns[j], cns[j+1] = cns[j+1], cns[j]   #비교했던 ns[j]와 그 다음의 순서인 ns[j+1]과의 값을 바꾸어 줌.</code></pre><p>  return cns</p>
</li>
<li><p>----실행 파일-----
import random
import copy</p>
</li>
</ul>
<p>students = []
for i in range(21):
    students.append(random.randint(170,185))
print(f&#39;students: {students}&#39;)</p>
<p>sortedStudents = bubbleSort(students, deepCopy=True)
print(f&#39;students: {students}&#39;)
print(f&#39;sortedStudents: {sortedStudents}&#39;)</p>
<p>...
students: [172, 177, 183, 171, 177, 175, 184, 173, 178, 181, 183, 170, 173, 180, 179, 172, 182, 178, 175, 180, 178]
students: [172, 177, 183, 171, 177, 175, 184, 173, 178, 181, 183, 170, 173, 180, 179, 172, 182, 178, 175, 180, 178]</p>
<h1 id="깊은-복사했기-때문에-students는-변형되지-않고-유지됨">깊은 복사했기 때문에 students는 변형되지 않고 유지됨</h1>
<p>sortedStudents: [170, 171, 172, 172, 173, 173, 175, 175, 177, 177, 178, 178, 178, 179, 180, 180, 181, 182, 183, 183, 184]</p>
<pre><code>## 삽입 정렬
- 삽입 정렬: 정렬되어 있는 자료 배열과 비교해서 정렬 위치를 찾고 값을 넣어줌.
![](https://velog.velcdn.com/images/sss_yeonii/post/5e6732db-77a2-42a4-88b5-1b13f14d10c0/image.png)
```python
class SortNumbers:

    def __init__(self, ns, asc=True):
        self.nums = ns
        self.isAsc = asc

    def isAscending(self, flag):
        self.isAsc = flag

    def setSort(self):

        for i1 in range(1, len(self.nums)):  # 2번째의 수부터 시작해서, 이전번째의 수가 현재의 수보다 크면 앞으로 이동 =&gt; range 1부터 시작
            i2 = i1 - 1  # 이전번째를 i2로 지정
            cNum = self.nums[i1]  # 현재 기준이 되는 숫자

            if self.isAsc:  #오름차순
                while self.nums[i2] &gt; cNum and i2 &gt;= 0:  # 이전번째의 인덱스가 0보다 작으면 안됨.
                    self.nums[i2 + 1] = self.nums[i2]
                    i2 -= 1
            else:  #내림차순
                while self.nums[i2] &lt; cNum and i2 &gt;= 0:  # 이전번째의 인덱스가 0보다 작으면 안됨.
                    self.nums[i2 + 1] = self.nums[i2]
                    i2 -= 1
            self.nums[i2 + 1] = cNum

    def getSortedNumbers(self):
        return self.nums

    def getMinNumbers(self):
        if self.isAsc:
            return self.nums[0]
        else:
            return self.nums[len(self.nums)-1]


    def getMaxNumbers(self):
        if self.isAsc:
            return self.nums[len(self.nums)-1]
        else:
            return self.nums[0]
-----실행 파일-----
import insertMod
import random
import copy
nums = random.sample(range(1, 1001), 10)
print(f&#39;numbers: {nums}&#39;)

sn = insertMod.SortNumbers(nums, asc=True)

# 오름차순
sn.setSort()
sortedNumbers = sn.getSortedNumbers()
print(f&#39;sortedNumbers by asc: {sortedNumbers}&#39;)

# 내림차순
sn.isAscending(False)
sn.setSort()
sortedNumbers = sn.getSortedNumbers()
print(f&#39;sortedNumbers by desc: {sortedNumbers}&#39;)

# 최솟값과 최댓값
print(f&#39;min: {sn.getMinNumbers()}&#39;)
print(f&#39;max: {sn.getMaxNumbers()}&#39;)

.....
numbers: [809, 715, 295, 586, 414, 2, 529, 638, 872, 510]
sortedNumbers by asc: [2, 295, 414, 510, 529, 586, 638, 715, 809, 872]
sortedNumbers by desc: [872, 809, 715, 638, 586, 529, 510, 414, 295, 2]
min: 2
max: 872</code></pre><h2 id="선택-정렬">선택 정렬</h2>
<ul>
<li><p>선택 정렬: 최소값을 찾아 맨 앞에 위치한 값과 교체하는 방식으로 자료를 정렬하는 알고리즘</p>
<ul>
<li>현재 값을 기준으로 현재 값을 포함한 다음의 숫자들 중 최솟값을 가장 맨 앞으로 교체
<img src="https://velog.velcdn.com/images/sss_yeonii/post/55e87dbb-a914-469b-9d61-97e251c97a52/image.png" alt=""></li>
</ul>
</li>
<li><p>실습: 선택정렬 알고리즘을 이용해서 학생 20명의 시험 점수를 오름차순과 내림차순으로 정렬하는 모듈을 만들어보자. 시험 점수는 50부터 100까지로 한다.
```python
def sortNumber(num, asc=True):
  if asc: #오름차순</p>
<pre><code>  for i in range(len(num)-1):
      minIdx = i

      for j in range(i+1, len(num)):
          if num[minIdx] &gt; num[j]:
              minIdx = j
      num[i], num[minIdx] = num[minIdx], num[i]</code></pre><p>  else: #내림차순</p>
<pre><code>  for i in range(len(num) - 1):
      minIdx = i

      for j in range(i + 1, len(num)):
          if num[minIdx] &lt; num[j]:
              minIdx = j
      num[i], num[minIdx] = num[minIdx], num[i]</code></pre><p>  return num</p>
</li>
<li><p>----- 실행 파일 -------
import selectSortMod as sm
import random
import copy
num = random.sample(range(50,101), 20)
print(f&#39;num: {num}&#39;)
print(f&#39;result ASC: {sm.sortNumber(copy.deepcopy(num))}&#39;)
#깊은 복사했기 때문에 원본이 정렬되지 않고 그대로 유지(훼손되지 않았음)</p>
</li>
</ul>
<p>print(f&#39;num: {num}&#39;) 
print(f&#39;result DESC: {sm.sortNumber(copy.deepcopy(num), asc=False)}&#39;)</p>
<p>.....
num: [59, 79, 66, 53, 81, 58, 91, 97, 68, 92, 75, 89, 50, 52, 80, 74, 71, 70, 72, 78]
result ASC: [50, 52, 53, 58, 59, 66, 68, 70, 71, 72, 74, 75, 78, 79, 80, 81, 89, 91, 92, 97]
num: [59, 79, 66, 53, 81, 58, 91, 97, 68, 92, 75, 89, 50, 52, 80, 74, 71, 70, 72, 78]
result DESC: [97, 92, 91, 89, 81, 80, 79, 78, 75, 74, 72, 71, 70, 68, 66, 59, 58, 53, 52, 50]</p>
<pre><code>
## 최댓값 알고리즘
- 자료 구조에서 가장 큰 값을 찾는다
```python
class MaxAlgorithm:

    def __init__(self, ns):
        self.nums = ns
        self.maxNum = 0

    def getMaxNum(self):
        self.maxNum = self.nums[0]

        for n in self.nums:
            if self.maxNum &lt; n:
                self.maxNum = n

        return self.maxNum

ma = MaxAlgorithm([-2, -4, 5, 7, 10, 0, 8, 20, -11])
maxVal = ma.getMaxNum()
print(f&#39;최댓값: {maxVal}&#39;)
......
최댓값: 20</code></pre><h2 id="최솟값-알고리즘">최솟값 알고리즘</h2>
<ul>
<li><p>자료 구조에서 가장 작은 값을 찾는다</p>
<pre><code class="language-python">class MinAlgorithm:

  def __init__(self, ns):
      self.nums = ns
      self.minNum = 0

  def getMinNum(self):
      self.minNum = self.nums[0]

      for n in self.nums:
          if self.minNum &gt; n:
              self.minNum = n

      return self.minNum
</code></pre>
</li>
</ul>
<p>ma = MinAlgorithm([-2, -4, 5, 7, 10, 0, 8, 20, -11])
minVal = ma.getMinNum()
print(f&#39;최솟값: {minVal}&#39;)
.....
최솟값: -11</p>
<pre><code>## 최빈값 알고리즘
- 데이터에서 빈도수가 가장 많은 데이터를 최빈값이라고 한다. 
![](https://velog.velcdn.com/images/sss_yeonii/post/7ae47be4-c226-49c6-aa50-f3f8251c6f11/image.png)
  - 데이터를 인덱스로 변환. 즉, nums의 값이 위치(=인덱스)인 indexes를 만들고 nums에 값이 존재할 때마다 1씩 더해주는 방식 
- 실습: 최빈값 알고리즘을 이용해서 학생 100명의 점수 분포를 다음과 같이 나타내 보자.
```python
class MaxAlgorithm:

    def __init__(self, ns):
        self.nums = ns
        self.maxNum = 0
        self.maxNumIdx = 0

    def getMaxNumAndIdx(self):
        self.maxNum = self.nums[0]
        self.maxNumIdx = 0

        for i,n in enumerate(self.nums):
            if self.maxNum &lt; n:
                self.maxNum = n
                self.maxNumIdx = i

    def getMaxNum(self):
        return self.maxNum

    def getMaxNumIdx(self):
        return self.maxNumIdx

----- 실행 파일 ------
import random
import max

scores = []

for i in range(11):
    rn = random.randint(71, 101)
    # if rn != 100:
    rn = rn - (rn % 5)
    scores.append(rn)
    #랜덤으로 뽑은 수가 100점만 아니면, 5로 나눈 나머지를 빼서 단위 5로 맞추어줌.

print(f&#39;scores: {scores}&#39;)
maxAlo = max.MaxAlgorithm(scores)
maxAlo.getMaxNumAndIdx()
maxNum = maxAlo.getMaxNum()
print(f&#39;maxNum: {maxNum}&#39;)
maxNumIdx = maxAlo.getMaxNumIdx()

#인덱스 리스트 생성
indexes = [0 for i in range(maxNum+1)] #maxNum+1을 해줘야 scores와 길이가 맞는다
print(f&#39;indexes: {indexes}&#39;)
print(len(indexes))

#인덱스 리스트에 빈도 저장
for n in scores:
    indexes[n] = indexes[n] + 1
print(f&#39;indexes: {indexes}&#39;)


n=1
while True:
    maxAlo = max.MaxAlgorithm(indexes)
    maxAlo.getMaxNumAndIdx()
    maxNum = maxAlo.getMaxNum()
    maxNumIdx = maxAlo.getMaxNumIdx()

    if maxNum == 0:
        break

    print(f&#39;{n}. {maxNumIdx} 빈도수: {maxNum}\t&#39;, end=&#39;&#39;)
    print(&#39;+&#39;*maxNum)

    indexes[maxNumIdx] = 0
    #가장 빈도수가 높은 값을 0으로 바꾸어서 최빈값을 초기화 -&gt; 다음 최빈값을 다음번째에 출력할 수 있음

    n += 1
......
scores: [85, 80, 80, 70, 80, 85, 75, 80, 75, 80, 80]
maxNum: 85
indexes: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
86
indexes: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 6, 0, 0, 0, 0, 2]
1. 80 빈도수: 6    ++++++
2. 75 빈도수: 2    ++
3. 85 빈도수: 2    ++
4. 70 빈도수: 1    +</code></pre><h2 id="근삿값-알고리즘">근삿값 알고리즘</h2>
<ul>
<li><p>근삿값: 특정 값에 가장 가까운 값</p>
<pre><code class="language-python">def getNearNum(avgNum): #near.py로 저장
 basicScores = [95, 85, 75, 65, 55]
 nearNum = 0
 minNum = 100

 for n in basicScores:
     absNum = abs(n-avgNum)
     #(기준값-평균값)인 차이가 가장 작은 수를 nearNum으로 추출
     if absNum &lt; minNum:
         minNum = absNum
         nearNum = n

 if nearNum == 95:
     return &#39;A&#39;
 elif nearNum == 85:
     return &#39;B&#39;
 elif nearNum == 75:
     return &#39;C&#39;
 elif nearNum == 65:
     return &#39;D&#39;
 elif nearNum &lt;= 55:
     return &#39;F&#39;
------실행 파일-----
import near
import random
</code></pre>
</li>
</ul>
<p>scores = random.sample(range(0,101),5)
print(f&#39;scores: {scores}&#39;)</p>
<p>totalScore = sum(scores)
print(f&#39;totalScore: {totalScore}&#39;)</p>
<p>avgScore = totalScore / len(scores)
print(f&#39;avgScore: {avgScore}&#39;)</p>
<p>grade = near.getNearNum(avgScore)
print(f&#39;grade: {grade}&#39;)</p>
<p>.....
scores: [80, 88, 79, 89, 78]
totalScore: 414
avgScore: 82.8
grade: B</p>
<pre><code>## 평균 알고리즘
- 평균: 여러 수나 양의 중간값을 갖는 수를 평균이라고 한다.
```python
def getAverageScore(scores):
    totalScore = 0

    for n in scores:
        totalScore += n

    avgScore = totalScore / len(scores)
    return avgScore

scores = [8.9, 7.6, 8.2, 9.1, 8.8, 8.1, 7.9, 9.4, 7.2, 8.7]
print(f&#39;averageScore: {getAverageScore(scores)}&#39;)
.....
averageScore: 8.39</code></pre><h2 id="재귀-알고리즘">재귀 알고리즘</h2>
<ul>
<li>재귀: 나 자신을 다시 호출하는 것
<img src="https://velog.velcdn.com/images/sss_yeonii/post/ace8ec8a-e50a-4c65-9bc1-b2ac96bc7956/image.png" alt="">
&lt;실습&gt;</li>
<li>팩토리얼 함수 구현하기<pre><code class="language-python">def factorial(num):
  if num &gt; 0:
      return num * factorial(num-1)
  else:
      return 1
</code></pre>
</li>
</ul>
<p>print(f&#39;factorial(10): {factorial(5)}&#39;)
.....
factorial(10): 120</p>
<pre><code>- 유클리드 호제법으로 최대 공약수 계산하기
  - 유클리드 호제법: 두 자연수 n1, n2에 대하여(이때 n1&gt;n2), n1을 n2로 나눈 나머지를 r이라고 할 때, n1과 n2의 최대 공약수는 n2와 r의 최대공약수와 같다.
  ![](https://velog.velcdn.com/images/sss_yeonii/post/13747296-6297-43f5-9d97-17e54923a409/image.png)
     - 96 / 40의 나머지: 16 -&gt; 40 / 16의 나머지: 8 -&gt; 16/8 == 0이기 때문에, n2인 8이 96과 40의 최대공약수
```python
def gcd(n1,n2):
    if n1 % n2 == 0: #나누어떨어지는 수이면 최대공약수는 더 작은 수인 n2
        return n2
    else:
        return gcd(n2, n1 % n2)

print(f&#39;gcd(82, 32): {gcd(82, 32)}&#39;)
print(f&#39;gcd(96,40): {gcd(96,  40)}&#39;)
.....
gcd(82, 32): 2
gcd(96,40): 8</code></pre><ul>
<li><p>사용자가 정수 두개를 입력하면 작은 정수와 큰 정수 사이의 모든 정수의 합을 구하는 프로그램을 재귀 알고리즘을 이용해서 만들어보자.</p>
<pre><code class="language-python">class NumsSum:

  def __init__(self, n1, n2):
      self.bigNum = 0
      self.smallNum = 0
      self.setN1N2(n1, n2)

  def setN1N2(self, n1, n2):
      self.bigNum = n1
      self.smallNum = n2

      if n1 &lt; n2:
          self.bigNum = n2
          self.smallNum = n1

  def addNum(self, n):
      if n &lt;= 1:
          return n

      return n + self.addNum(n - 1)

  def sumBetweenNums(self):
      return self.addNum(self.bigNum - 1) - self.addNum(self.smallNum)
</code></pre>
</li>
</ul>
<p>-----실행 파일-----
import mod</p>
<p>num1 = int(input(f&#39;input number1: &#39;))
num2 = int(input(f&#39;input number2: &#39;))
ns = mod.NumsSum(num1, num2)
result = ns.sumBetweenNums()
print(f&#39;result: {result}&#39;)</p>
<p>.....
input number1: 10
input number2: 3
result: 39</p>
<pre><code>## 하노이의 탑
![](https://velog.velcdn.com/images/sss_yeonii/post/cd104891-79b7-4ca1-b016-7d52fb2f58f0/image.png)
```python
# 원판 개수, 출발 기둥, 도착 기둥, 경유 기둥
def moveDisc(discCnt, fromBar, toBar, viaBar):
    if discCnt == 1:
        print(f&#39;{discCnt}disc: {fromBar}에서 {toBar}(으)로 이동!&#39;)

    else:
        # (discCnt-1)개들을 경유 기둥으로 이동
        moveDisc(discCnt-1, fromBar, viaBar, toBar)
        # discCnt를 목적 기둥으로 이동
        print(f&#39;{discCnt}disc: {fromBar}에서 {toBar}(으)로 이동!&#39;)
        # (discCnt-1)개들을 도착 기둥으로 이동
        moveDisc(discCnt-1, viaBar, toBar, fromBar)

moveDisc(3, 1, 3, 2)
....
1disc: 1에서 3(으)로 이동!
2disc: 1에서 2(으)로 이동!
1disc: 3에서 2(으)로 이동!
3disc: 1에서 3(으)로 이동!
1disc: 2에서 1(으)로 이동!
2disc: 2에서 3(으)로 이동!
1disc: 1에서 3(으)로 이동!</code></pre><h2 id="병합-정렬">병합 정렬</h2>
<ul>
<li><p>자료구조를 분할하고 각각의 분할된 자료구조를 정렬한 후 다시 병합하여 정렬한다.</p>
<ul>
<li>합칠 때 각 수의 크고 작음을 비교해서 작은 수를 왼쪽으로 자리바꿈하면서 병렬 반복하여 정렬 진행
<img src="https://velog.velcdn.com/images/sss_yeonii/post/ba1f0228-2b0c-4d31-ae85-ad5cd1d6f02b/image.png" alt=""><img src="https://velog.velcdn.com/images/sss_yeonii/post/9276495f-7cb6-4043-bbfa-6d22027782e1/image.png" alt="">
&lt;실습&gt;</li>
</ul>
</li>
<li><p>1~100 정수 중 10개의 난수 추출한 후, 병합 정렬 활용해 내림차순/오름차순으로 정렬하라.</p>
<pre><code class="language-python">def mSort(ns, ACS = True):

  if len(ns) &lt; 2:
      return ns

  #분할
  midIdx = len(ns) // 2  #중간값
  leftNums = mSort(ns[0:midIdx], ACS=ACS) #처음부터 중간값까지
  # 이때 ACS=ACS를 넣어주어야, ACS=False 로 처음에 넣었던 값이 재귀로 돌아갈 때도 반영될 수 있음!
  rightNums = mSort(ns[midIdx:len(ns)], ACS=ACS) #중간값부터 끝까지

  #병합
  mergeNums = []
  leftIdx = 0; rightIdx = 0
  if ACS:
      while leftIdx &lt; len(leftNums) and rightIdx &lt; len(rightNums):
          # 자리 바꿈
          if leftNums[leftIdx] &lt; rightNums[rightIdx]:
              mergeNums.append(leftNums[leftIdx])
              leftIdx += 1
          else:
              mergeNums.append(rightNums[rightIdx])
              rightIdx += 1

  else:
      while leftIdx &lt; len(leftNums) and rightIdx &lt; len(rightNums):
          # 자리 바꿈
          if leftNums[leftIdx] &gt; rightNums[rightIdx]:
              mergeNums.append(leftNums[leftIdx])
              leftIdx += 1

          else:
              mergeNums.append(rightNums[rightIdx])
              rightIdx += 1

  mergeNums = mergeNums + leftNums[leftIdx:]
  mergeNums = mergeNums + rightNums[rightIdx:]

  return mergeNums

</code></pre>
</li>
</ul>
<p>import random
import copy</p>
<p>ns = random.sample(range(1,101), 10)
nums = copy.deepcopy(ns)</p>
<p>print(f&#39;not sorted nums: {ns}&#39;)</p>
<p>print(f&#39;mSort(nums) by ASC: {mSort(nums, ACS=True)}&#39;)
print(f&#39;mSort(nums) by DESC: {mSort(nums, ACS=False)}&#39;)
.....
not sorted nums: [41, 73, 56, 59, 45, 51, 27, 16, 35, 19]
mSort(nums) by ASC: [16, 19, 27, 35, 41, 45, 51, 56, 59, 73]
mSort(nums) by DESC: [73, 59, 56, 51, 45, 41, 35, 27, 19, 16]</p>
<pre><code>
## 퀵 정렬
- 기준 값보다 작은 값과 큰 값으로 분리한 후 다시 합친다.
![](https://velog.velcdn.com/images/sss_yeonii/post/0ea7e7d9-6284-476a-97d8-7c676c3f367e/image.png)
&lt;실습&gt;
- 1부터 100까지의 난수 10개를 생성하고, 다음의 요구 사항을 만족하는 모듈을 만들어보자.
```python
def qSort(ns, acs=True):
    if len(ns) &lt; 2:
        return ns

    midIdx = len(ns) // 2
    midVal = ns[midIdx] #기준값
    smallNums = []  #왼쪽은 기준값보다 작은 수
    sameNums = []   # 기준값과 동일한 값
    bigNums = []    #오른쪽은 기준값보다 큰 수

    for n in ns:
        if n &lt; midVal:
            smallNums.append(n)
        elif n == midVal:
            sameNums.append(n)
        else:
            bigNums.append(n)

    if acs:
        return qSort(smallNums) + sameNums + qSort(bigNums)
    else:
        return qSort(bigNums, acs=acs) + sameNums + qSort(smallNums, acs=acs)

import random
import copy

ns = random.sample(range(1,101), 10)
nums = copy.deepcopy(ns)

print(f&#39;not sorted nums: {ns}&#39;)

print(f&#39;qSort(nums) by ASC: {qSort(nums, acs=True)}&#39;)
print(f&#39;qSort(nums) by DESC: {qSort(nums, acs=False)}&#39;)
.....
not sorted nums: [40, 46, 86, 94, 49, 13, 26, 7, 52, 97]
qSort(nums) by ASC: [7, 13, 26, 40, 46, 49, 52, 86, 94, 97]
qSort(nums) by DESC: [97, 94, 86, 52, 49, 46, 40, 26, 13, 7]</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Lv.0]]></title>
            <link>https://velog.io/@sss_yeonii/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Lv.0</link>
            <guid>https://velog.io/@sss_yeonii/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Lv.0</guid>
            <pubDate>Sat, 22 Jun 2024 15:44:47 GMT</pubDate>
            <description><![CDATA[<h3 id="특수-문자-출력하는-방법">&lt; 특수 문자 출력하는 방법 &gt;</h3>
<h4 id="1-r-을-앞에-붙인다">1. r 을 앞에 붙인다</h4>
<pre><code class="language-python">print(r&#39;!@#$%^&amp;*(\&#39;&quot;&lt;&gt;?:;&#39;)</code></pre>
<h4 id="2-역슬래시를----앞에-붙인다">2. (역슬래시)를 , &#39;, &quot; 앞에 붙인다</h4>
<pre><code class="language-python">print(&#39;!@#$%^&amp;*(\\\&#39;\&quot;&lt;&gt;?:;&#39;)</code></pre>
<h4 id="특수문자-종류">[특수문자 종류]</h4>
<pre><code class="language-python">&quot;\n&quot; #줄바꿈
&quot;\t&quot; # tab
&quot;\\&quot; # 백슬래시(\)
&quot;\&quot;&quot; # 큰 따옴표(&quot;)
&quot;\&#39;&quot; # 작은 따옴표(&#39;)</code></pre>
<h3 id="조건-문자열">&lt; 조건 문자열 &gt;</h3>
<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/2baebfcf-8c74-42bc-af66-159f1927afc6/image.png" alt=""><img src="https://velog.velcdn.com/images/sss_yeonii/post/89c2d3e0-2708-43ab-9aab-71f0353fe3f3/image.png" alt=""></p>
<blockquote>
<p>eval() : 문자열로 표현되는 표현식을 실행해서 결과값을 받아오는 함수 (<a href="https://hbase.tistory.com/397">참고 링크</a>)</p>
</blockquote>
<pre><code class="language-python">def solution(ineq, eq, n, m):
    return int(eval(str(n)+ineq+eq.replace(&quot;!&quot;, &quot;&quot;)+str(m)))

def solution(ineq, eq, n, m):
    if eq == &#39;!&#39;:
        eq = &#39;&#39;
    return int(eval(f&#39;{n} {ineq}{eq} {m}&#39;))

def solution(ineq, eq, n, m):
    answer = 0
    if n &gt; m and ineq ==&quot;&gt;&quot;:
        answer = 1
    elif n &lt; m and ineq == &quot;&lt;&quot;:
        answer = 1
    elif n == m and eq == &quot;=&quot;:
        answer = 1

    return answer</code></pre>
<h3 id="주사위-게임-2">&lt; 주사위 게임 2 &gt;</h3>
<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/136e8506-d943-4c2a-be78-fdc4185183b5/image.png" alt="">
&lt; 내가 작성한 코드 &gt;</p>
<pre><code class="language-python">def solution(a, b, c):
    if a == b == c:
        answer = (a + b + c) * (a**2 + b**2 + c**2 ) * (a**3 + b**3 + c**3)
    elif a == b or a == c or b == c:
        answer = (a + b + c) * (a**2 + b**2 + c**2 )
    else:
        answer = a + b + c
    return answer</code></pre>
<p>&lt; 다른 사람이 작성한 코드&gt;
중복값을 허용하지 않는 set()로 만들어서 길이로 if문을 돌리다니..</p>
<pre><code class="language-python">def solution(a, b, c):
    check=len(set([a,b,c]))
    if check==1:
        return 3*a*3*(a**2)*3*(a**3)
    elif check==2:
        return (a+b+c)*(a**2+b**2+c**2)
    else:
        return (a+b+c)</code></pre>
<h3 id="수-조작하기-1">&lt; 수 조작하기 1 &gt;</h3>
<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/811a63bb-b478-491c-ac6e-2bf79237b4cd/image.png" alt=""></p>
<p>&lt; 내가 작성한 코드 &gt;</p>
<pre><code class="language-python">def solution(n, control):
    for i in control:
        if i == &#39;w&#39;:
            n += 1
        elif i == &#39;s&#39;:
            n -= 1
        elif i ==&#39;d&#39;:
            n+= 10
        elif i == &#39;a&#39;:
            n-= 10
    return n</code></pre>
<p>&lt; 다른 사람이 작성한 코드 &gt;
zip()과 dict()로 이렇게 간단히 만들 수 있다니..</p>
<pre><code class="language-python">def solution(n, control):
    key = dict(zip([&#39;w&#39;,&#39;s&#39;,&#39;d&#39;,&#39;a&#39;], [1,-1,10,-10]))
    return n + sum([key[c] for c in control])</code></pre>
<blockquote>
<p><strong>[ zip() ]</strong> (<a href="https://www.daleseo.com/python-zip/">https://www.daleseo.com/python-zip/</a>)
zip() 함수는 여러 개의 순회 가능한(iterable) 객체를 인자로 받고, 각 객체가 담고 있는 원소를 튜플의 형태로 차례로 접근할 수 있는 반복자(iterator)를 반환합니다. 설명이 좀 어렵게 들릴 수도 있는데요. 간단한 예제를 보면 이해가 쉬우실 겁니다.</p>
</blockquote>
<pre><code class="language-python">numbers = [1, 2, 3]
letters = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;]
for pair in zip(numbers, letters):
     print(pair)
...
(1, &#39;A&#39;)
(2, &#39;B&#39;)
(3, &#39;C&#39;)</code></pre>
<h3 id="수열과-구간-쿼리-3">&lt; 수열과 구간 쿼리 3 &gt;</h3>
<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/e8cea457-7036-4ee8-87ad-39f4d7fa2126/image.png" alt=""></p>
<p>아래와 같은 방식으로 값을 변경할 수도 있구나!</p>
<pre><code class="language-python">def solution(arr, queries):
    for a,b in queries:
        arr[a],arr[b]=arr[b],arr[a]
    return arr</code></pre>
<h3 id="카운트-업">&lt; 카운트 업 &gt;</h3>
<p><img src="https://velog.velcdn.com/images/sss_yeonii/post/6d058de3-ee57-4922-a916-6185eab3d5b9/image.png" alt="">
&lt; 내 코드 &gt;</p>
<pre><code class="language-python">def solution(start_num, end_num):
    answer =[]
    for i in range(start_num, end_num+1):
        answer.append(i)
    return answer</code></pre>
<p>&lt; 다른 사람의 풀이 &gt;</p>
<ul>
<li>append()를 사용하지 않고, list()나 []를 사용해서도 리스트를 생성할 수 있다 =&gt; 어떻게 하면 코드를 간단하게 만들어낼 수 있을지를 고민하게 되는듯<pre><code class="language-python">def solution(start, end):
  return list(range(start, end + 1))
</code></pre>
</li>
</ul>
<p>def solution(start, end):
return [i for i in range(start,end+1)]
```</p>
]]></description>
        </item>
    </channel>
</rss>