<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Chris-Yang.log</title>
        <link>https://velog.io/</link>
        <description>sharing all the world</description>
        <lastBuildDate>Wed, 24 Aug 2022 14:42:26 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Chris-Yang.log</title>
            <url>https://images.velog.io/images/max-sum/profile/21fcb599-6525-4c77-93a2-63ee3fc459c1/IMG_5215.JPG</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. Chris-Yang.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/max-sum" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[python | fabric | solved | ERROR 2002 (HY000): Can't connect to local server through socket '/run/mysqld/mysqld.sock' (2)]]></title>
            <link>https://velog.io/@max-sum/python-fabric-solved-ERROR-2002-HY000-Cant-connect-to-local-server-through-socket-runmysqldmysqld.sock-2</link>
            <guid>https://velog.io/@max-sum/python-fabric-solved-ERROR-2002-HY000-Cant-connect-to-local-server-through-socket-runmysqldmysqld.sock-2</guid>
            <pubDate>Wed, 24 Aug 2022 14:42:26 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/max-sum/post/e01553c5-a464-4a35-834a-0b5163ed3d48/image.png" alt=""></p>
<br/>

<h2 id="사건발생">&gt; 사건발생</h2>
<h3 id="▶-상황">▶ 상황</h3>
<p><img src="https://velog.velcdn.com/images/max-sum/post/f14ea849-a352-4298-b6e5-7a41b9d5fc72/image.png" alt=""></p>
<ul>
<li>python fabric으로 mariadb docker container에 db dump를 하는 중이었습니다.</li>
<li>터미널에 스크립트로 입력하는 경우 이상 없이 진행되던 명령어들이었습니다</li>
<li>그러나 fabric을 통해 실행하니 <code>ERROR 2002 (HY000): Can&#39;t connect to local server through socket &#39;/run/mysqld/mysqld.sock&#39; (2)</code>라는 error가 발생하였습니다.</li>
<li>error가 발생되는 코드는 db dump를 하는 <code>sudo(&#39;docker exec mariadb sh /mariadb_script/create_db.sh&#39;)</code>였습니다.</li>
</ul>
<br/>

<h2 id="수사-착수">&gt; 수사 착수</h2>
<h3 id="▶-추적">▶ 추적</h3>
<ul>
<li>우선 구글링을 통해서는 별다른 해결 방법이 없었습니다.</li>
<li>그러던 중 해당 로직을 2번 실행하는 경우 진행되는 케이스를 통해 사용하려는 컨테이너가 실행되고 있으면 진행된다는 사실을 발견하였습니다.</li>
<li>그러나 fabric은 에러가 발생하면 멈추기 때문에 이 상태로는 fabric 특성상 반드시 사용하는 기능별 함수 연계를 구현할 수 없었습니다.</li>
<li>컨테이너를 미리 구동시켜놓으면 되긴 했지만 그럴 수 없는 케이스와 마주할 수도 있고, 원인을 모르고 넘어가고 싶지도 않았습니다.(사실 약간의 시간적 여유가 있어서 파고듦)</li>
</ul>
<br/>

<h3 id="▶-검거">▶ 검거</h3>
<ul>
<li>&quot;컨테이너가 미리 구동 중이면 된다&quot;는 사실과 &quot;fabric 에러가 발생하지 않아야 한다&quot;는 조건 안에서 할 수 있는 첫번째 방법은 은 <code>sudo(&#39;docker-compose up -d&#39;)</code>을 연달아 2번 넣는 방법이었고 성공했습니다.</li>
<li>하지만 방법의 무식함이 마음에 안들었고 잠시 생각하던 중 문득 해당 컨테이너가 올라가서 안정되기 전에 db dump가 실행되기 때문에 문제가 발생했을거라는 생각이 들었습니다.</li>
<li>그리하여 docker-compose 꾸러미가 올라가는 코드와 db dump를 시작하는 코드 사이 간격을 주기 위해 sleep을 사용해 보았고 성공하였습니다.<pre><code class="language-py">sudo(&#39;docker-compose up -d&#39;)
for i in range(1, 3 + 1):
  time.sleep(1)
  print(f&#39;--&gt; For stable next step.. Now pass about \&quot;{i} second\&quot; after start&#39;)
</code></pre>
</li>
</ul>
<p>sudo(&#39;docker exec mariadb sh /mariadb_script/create_db.sh&#39;) </p>
<h2 id="">```</h2>
<p>[20220825 추가]</p>
<ul>
<li>빠르게 동일한 원인으로 문제가 발생하였습니다.</li>
<li>해당 로직 이후 바로 다시 docker container를 실행시켜야 했는데 ``requests.exceptions.ConnectionError: ...` 에러가 떴고 위와 같이 sleep을 연계해주어 즉시 해결하였습니다.</li>
</ul>
<br/>

<h3 id="🌈작은-회고">🌈작은 회고</h3>
<p>한달 전 쯤 cto님이 &quot;우리와 가장 닮은 직업이 뭐라고 생각하시느냐&quot;라고 물어보셨다.</p>
<p>&quot;음.. 노가다..?&quot;라고 속으로만 말했었다.</p>
<p>그리고 곧이어 이렇게 말씀하였다.
&quot;저는 형사라고 생각합니다.
작은 단서들을 모아 사건을 해결하는 모습이 형사와 비슷하다고 생각됩니다
우리는 error log를 통해 얻은 단서들을 통해 문제를 해결해야 합니다.&quot;</p>
<p>오늘도 이말에 공감했고 또다른 닮은 점도 떠올랐다.
며칠동안 자동차 안에서 철야로 잠복근하는 모습,
그래서 못씻어서 벅벅 긁으며 전방을 주시하는 모습.</p>
<p>한 때 형사가 꿈이었던 나는 지금 행복할듯 말듯한
묘한 기분이 든다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[python | fabric | solved | PermissionError: [Errno 13] Permission denied]]></title>
            <link>https://velog.io/@max-sum/python-solved-PermissionError-Errno-13-Permission-denied</link>
            <guid>https://velog.io/@max-sum/python-solved-PermissionError-Errno-13-Permission-denied</guid>
            <pubDate>Mon, 22 Aug 2022 08:06:39 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/max-sum/post/bd67bf5d-1ef5-4458-92ef-b9e7a9b007bb/image.png" alt="sample_image"></p>
<h2 id="문제">&gt; 문제</h2>
<h3 id="▶-python을-통한-파일-조작-시-문제-발생">▶ python을 통한 파일 조작 시 문제 발생</h3>
<ul>
<li><p>프로젝트 자동 설치/ 빌드를 위해 python fabric을 이용하여 스크립트를 만들다가 다음과 같은 문제가 발생하였습니다.</p>
</li>
<li><p>문제 발생 코드</p>
<pre><code class="language-shell">  with open(path, mode=&#39;w&#39;) as file:
      file.write(new_file_content)</code></pre>
</li>
<li><p>에러 코드</p>
<pre><code class="language-shell">  PermissionError: [Errno 13] Permission denied</code></pre>
</li>
</ul>
<br/>

<h3 id="▶-해결">▶ 해결</h3>
<ul>
<li><p>원인: 권한 문제</p>
</li>
<li><p>과정</p>
<ul>
<li><code>chmod x+ /home/계정이름/your_project_name/.env&#39;</code>을 적용하였으나 해결되지 않았습니다.</li>
<li>다음으로 <code>chown 계정이름 /home/계정이름/your_project_name/.env</code>을 적용하여 문제가 발생한 파일을 해당 계정 소유로 바꾸니 해결되어 파일을 수정할 수 있었습니다.</li>
<li>변경된 권한 참고: <code>-rwxr-xr-x  1 계정이름     ubuntu   442 Aug 22 07:28 .env</code></li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Data visualization tool | knowi]]></title>
            <link>https://velog.io/@max-sum/Data-visualization-tool-knowi</link>
            <guid>https://velog.io/@max-sum/Data-visualization-tool-knowi</guid>
            <pubDate>Tue, 22 Mar 2022 15:48:54 GMT</pubDate>
            <description><![CDATA[<h2 id="knowi-소개와-특징">&gt; knowi 소개와 특징</h2>
<p><img src="https://images.velog.io/images/max-sum/post/4c917bcf-9cbb-4075-afd0-cfbe1b2a4c24/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.18.45.png" alt=""></p>
<h3 id="▶︎-data-visualization-tool">▶︎ data visualization tool</h3>
<p>시계열(time series, 일정 시간 간격으로 배치된 데이터들의 수열) 매트릭 데이터를 시각화한 대시보드를 제공해주는 오픈소스 도구입니다.</p>
<p>knowi는 데스크톱 설치를 지원하지 않고 웹 브라우저를 통해 액세스 할 수있는 온 프레미스 버전과 클라우드 지원 플랫폼을 보유하고 있습니다. </p>
<p>기업 사용자에게 온 프레미스/클라우드/하이브리드 배포 옵션을 제공합니다.</p>
<blockquote>
<p>🥕 공식 홈페이지:
<a href="https://www.knowi.com/plans/">https://www.knowi.com/plans/</a></p>
</blockquote>
<br/>

<h3 id="▶︎-장점">▶︎ 장점</h3>
<p>코딩 경험이 없어도 데이터세트에 액세스하고 대시보드를 구축할 수 있습니다.</p>
<p>REST API 통합은 API에 연결하고 다른 데이터 소스에서 결과를 변환 및 결합 할 수 있다는 점에서 특히 뛰어납니다.</p>
<p>다른 BI 플랫폼과 달리 NoSQL 데이터 소스에 대한 기본 커넥터와 함께 제공되므로 타사 드라이버를 설치할 필요가 없으며 데이터를 관계화할 필요없습니다.</p>
<p>NoSQL DB와의 기본 통합을 통해 사용자가 기존 BI 도구에서 지원하지 않는 기능인 비정형 데이터를 직접 분석 할 수 있도록 하는데, 이는 데이터를 이동하는 데 필요한 시간과 소모적이고 번거로운 단계를 제거하여 데이터 아키텍처를 단순화합니다.</p>
<p>기본 데이터 구조를 고려하지 않고 모든 유형의 데이터로 작업 할 수 있도록하는 데이터 가상화 계층에 의해 구조화/비구조화 데이터, 크고 작은 데이터와 관계없이 모든 유형의 데이터로 작업 할 수 있습니다.</p>
<p>구조화 된 데이터베이스와 구조화되지 않은 데이터베이스간에 조인 작업을 수행 할 수 있습니다.</p>
<p>Natural Language BI 플랫폼에서 제공하는 기능인 검색 기반 분석을 지원하여 영어로 질문하고 즉시 답변을 얻을 수 있습니다.</p>
<br/>

<h3 id="▶︎-단점">▶︎ 단점</h3>
<p>데이터 엔지니어를위한 사용자 인터페이스는 정교하지만 익숙해지는데 약간의 시간이 걸릴 수 있습니다.</p>
<p>공식 홈페이지에 커뮤니티 페이지가 존재하지만 거의 모든 카테고리 첫 페이지에 2~3년 전 작성된 글이 보이는 등 거의 이용되지 않는 수준이며 별도의 커뮤니티 역시 존재하지 않는 것으로 보입니다.</p>
<br/>

<h2 id="지원-데이터-소스">&gt; 지원 데이터 소스</h2>
<p>공식 홈페이지에 표기된 Supported data sources는 26종으로 세부 목록은 다음과 같습니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/3d44894a-19a6-4b4d-9bac-6a3b2b57d32b/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.49.30.png" alt=""></p>
<blockquote>
<p>🥕 출처: 
<a href="https://www.knowi.com/">https://www.knowi.com/</a> -&gt; 상단 Resources 메뉴 -&gt; Datasources</p>
</blockquote>
<br/>

<h2 id="표현-양식-종류">&gt; 표현 양식 종류</h2>
<p><img src="https://images.velog.io/images/max-sum/post/0d0d00c1-8eb7-4e36-9ed8-ec88036a2c3c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.14.06.png" alt=""></p>
<p>기본 표현 양식은 38종으로 구성되어 있습니다.</p>
<blockquote>
<p>🥕 <strong>데이터 표현 양식</strong>
<a href="https://docs.knowi.com/hc/en-us/articles/115006572748-Area">https://docs.knowi.com/hc/en-us/articles/115006572748-Area</a></p>
</blockquote>
<br/>

<h2 id="커스터마이징--개발-용이성">&gt; 커스터마이징 / 개발 용이성</h2>
<p>대시보드 커스터마이징이 가능하며 데이터를 시각적으로 표시하는 데 사용할 수있는 30개 이상의 시각화를 지원합니다. </p>
<p>또한 특정 요구사항을 충족하기 위해 Javascript를 사용하여 사용자 지정 시각화를 만들 수 있습니다.</p>
<p>하지만 커스텀 대시보드를 공유하는 웹페이지 등의 장소를 찾을 수 없었고 직접 제작하여 사용해야 할 것으로 보입니다.</p>
<blockquote>
<p>🥕 <strong>커스터마이징 페이지</strong>:
<a href="https://www.knowi.com/docs/visualizations.html#CustomWidgets">https://www.knowi.com/docs/visualizations.html#CustomWidgets</a></p>
</blockquote>
<br/>

<h2 id="라이센스--비용">&gt; 라이센스 / 비용</h2>
<h3 id="▶︎-라이센스-종류">▶︎ 라이센스 종류</h3>
<p>Basic, Team, Enterprise 세 가지 라이센스가 있습니다.</p>
<br/>

<h3 id="▶︎-라이센스별-요금정책">▶︎ 라이센스별 요금정책</h3>
<ul>
<li><p>Knowi는 맞춤형 연간 요금제를 제공하며 이를 얻으려면 영업팀에 문의해야 합니다</p>
</li>
<li><p>웹에서 찾을 수 있는 요금 관련 정보들은 다음과 같습니다.</p>
<ul>
<li>Knowi는 사용자를 버킷으로 그룹화하므로 사용자 기반이 증가함에 따라 비용 효율성이 높아집니다.</li>
<li>사용자를 버킷으로 그룹화하므로 사용자 기반이 증가함에 따라 비용 효율성이 높아집니다.</li>
<li>가격은 스타트업에 너무 비쌉니다.</li>
<li>스타트업 및 비영리단체를 위한 할인도 제공합니다</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Data visualization tool | tableau]]></title>
            <link>https://velog.io/@max-sum/Data-visualization-tool-tableau</link>
            <guid>https://velog.io/@max-sum/Data-visualization-tool-tableau</guid>
            <pubDate>Tue, 22 Mar 2022 09:22:07 GMT</pubDate>
            <description><![CDATA[<h2 id="tableau-소개와-특징">&gt; tableau 소개와 특징</h2>
<p><img src="https://images.velog.io/images/max-sum/post/0d19fd49-7b8c-4a72-befc-8b38069b6533/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.49.50.png" alt=""></p>
<h3 id="▶︎-data-visualization-tool">▶︎ Data visualization tool</h3>
<p>실시간으로 데이터를 시각적으로 변환하여 표현해 주는 데이터 시각화 도구입니다.</p>
<blockquote>
<p>🥕 <strong>공식 홈페이지</strong>:
<a href="https://www.tableau.com/ko-kr">https://www.tableau.com/ko-kr</a></p>
</blockquote>
<br/>

<h3 id="▶︎-장점">▶︎ 장점</h3>
<p>전문적인 코딩 지식이 없더라도 UI,UX디자인어를 위한 다양한 종류의 시각화 차트를 내장하고 있고 내장차트를 마우스 클릭과 드레그로 간단하게 시각화 및 AI기반 통계 모델링을 할 수 있습니다.</p>
<p>또한 시각화 할 수 있는 지원 데이터 소스가 단순 텍스트파일에서 DataBase, Excel 등 수용하는 종류의 폭이 넓고 구체적인 대상 또한 100여개에 달합니다.</p>
<p>자연어를 사용한 질문이 가능하며 질문을 통해 시각적 형태로 대답해주고 비즈니스 맥락에 알맞은 인사이트를 대시보드 형태로 답변을 얻어낼 수 있다는 특징이 있습니다.</p>
<p>뷰 및 대시 보드에 대한 데이터 기반 알림을 지원하여 데이터에서 특정 이상이 감지되거나 특정 임계 값이 충족 될 때 트리거 되어 이메일 형태로 지정된 사람에게 자동으로 전송됩니다.</p>
<p>또한 통계 분석을 포함하여 다양한 모델과 전문적인 재무통계 분석 기능을 갖추고 있으며 R언어도 지원합니다.</p>
<blockquote>
<p>💡 <strong>R언어</strong>: 통계 및 그래프 작업을 위한 인터프리터 프로그래밍 언어</p>
</blockquote>
<br/>

<h3 id="▶︎-단점">▶︎ 단점</h3>
<p>application framework가 제공하는 테이블 유형이 리스트, 크로스탭, 피벗 테이블 세가지 뿐으로 정형화되지 않은 스타일의 대시보드를 만들기에는 기능이 부족하여 필요에 따른 다양한(기업마다 양식이 상이한 불규칙한 보고서(표), 그룹 재무제표) 스타일로의 커스텀은 어렵습니다.</p>
<p>데이터 추가•삭제를 위해 DB에서 데이터를 입력하는 경우 data writeback을 지원하지 않아서 별도의 프로세스 필요로 합니다.</p>
<p>보안과 관련하여 Public을 통해 분석 및 시각화를 하게 되면, 원본 데이터 전세계로 공유되기 때문에 경우에 따라 매우 취약한 부분일 수 있습니다.
(암호 지정 기능이 있지만 찝찝한 부분입니다.)</p>
<blockquote>
<p>🥕 <strong>대시보드 암호 지정</strong>:
<a href="https://brunch.co.kr/@cheonmyung/93">https://brunch.co.kr/@cheonmyung/93</a></p>
</blockquote>
<br/>

<h3 id="▶︎-서비스별-특징">▶︎ 서비스별 특징</h3>
<ul>
<li><p>Desktop:</p>
<ul>
<li>tableau의 가장 기본 제품으로 데이터 소스에 연결 및 분석 수행과 리포트를 만들어줍니다.</li>
</ul>
</li>
<li><p>Server:</p>
<ul>
<li>Desktop에서 생산된 컨텐츠들을 공유 및 배포합니다.</li>
<li>데이터 연결, 리포트 생성과 배포를 위해 기본 1개의 Desktop이 필요합니다.</li>
<li>협업 관련 권한 관리, 사용자 통계, 데이터 스케줄링 등의 기능이 있습니다.</li>
</ul>
</li>
<li><p>Online:</p>
<ul>
<li>tableau의 SaaS 서비스이며 Server 제품과 기능은 동일하고 서버를 tableau에서 관리하는 cloud 제품입니다.</li>
</ul>
</li>
</ul>
<br/>
<br/>

<h2 id="지원-데이터-소스">&gt; 지원 데이터 소스</h2>
<p>공식 홈페이지에 표기된 Supported data sources는 90종으로 세부 목록은 링크를 통해 확인 가능합니다.</p>
<blockquote>
<p>🥕 <strong>지원 가능 데이터 소스</strong>:
<a href="https://help.tableau.com/current/pro/desktop/ko-kr/exampleconnections_overview.htm">https://help.tableau.com/current/pro/desktop/ko-kr/exampleconnections_overview.htm</a></p>
</blockquote>
<br/>
<br/>

<h2 id="표현-양식-종류">&gt; 표현 양식 종류</h2>
<p><img src="https://images.velog.io/images/max-sum/post/14e449c2-b2d3-4498-b962-28319e9f7a21/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.32.22.png" alt=""></p>
<p>기본 데이터 표현 양식은 15종으로 구성되어 있습니다.</p>
<blockquote>
<p>🥕 <strong>양식 페이지</strong>:
<a href="https://help.tableau.com/current/pro/desktop/ko-kr/dataview_examples.htm">https://help.tableau.com/current/pro/desktop/ko-kr/dataview_examples.htm</a></p>
</blockquote>
<br/>

<p><img src="https://images.velog.io/images/max-sum/post/5b7d38f0-7522-4a53-893a-46e211b22689/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.22.12.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/91c72cb5-c399-4c79-8145-bc90e3f4a878/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.59.19.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/6324ced8-f039-4474-9a65-4817c01a24ac/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.55.46.png" alt=""></p>
<p>표현양식과 관련하여 가상 갤러리, 제작 스토리 도입, 창작자 소개 등 자체적으로 visualization과 관련된 커뮤니티를 운영하며 매우 활성화 되어있습니다.</p>
<p>추천 양식의 질이 우수하고 매우 많은 양식이 공유되어 선택의 폭이 넓으며 단순히 만들어져 업로드된 양식의 숫자는 2022년 3.22일 현재 390만개에 달합니다.</p>
<blockquote>
<p>🥕 <strong>커뮤니티</strong>:</p>
</blockquote>
<ul>
<li>커스텀: <a href="https://www.tableau.com/ko-kr/community/public#kevin-wee">https://www.tableau.com/ko-kr/community/public#kevin-wee</a></li>
<li>질의: <a href="https://community.tableau.com/s/explore-forums?_ga=2.134501361.1214400979.1647909340-1767330237.1647909340&amp;_gac=1.45619670.1647955242.Cj0KCQjw5-WRBhCKARIsAAId9FnWX5Y_W6wiP_Tv8yjhIWNaXnuEWcxcUq-U6SD_ubEDeetONN0IHXoaAuJkEALw_wcB">https://community.tableau.com/s/explore-forums?_ga=2.134501361.1214400979.1647909340-1767330237.1647909340&amp;_gac=1.45619670.1647955242.Cj0KCQjw5-WRBhCKARIsAAId9FnWX5Y_W6wiP_Tv8yjhIWNaXnuEWcxcUq-U6SD_ubEDeetONN0IHXoaAuJkEALw_wcB</a></li>
</ul>
<br/>
<br/>

<h2 id="커스터마이징--개발-용이성">&gt; 커스터마이징 / 개발 용이성</h2>
<p>대시보드 커스터마이징이 가능하며 공식 홈페이지에서 이에 관한 동영상 강의를 제공하고 있습니다.</p>
<p>이미 만들어져 공유되는 대시보드의 수가 상당하여 특별한 경우가 아닌 이상 가져다 쓰면 되므로 개발 속도에 도움이 될 것 같습니다.</p>
<blockquote>
<p>🥕 <strong>커스터마이징 강의(Destop -&gt; 비주얼리제이션)</strong>:
<a href="https://www.tableau.com/ko-kr/support/knowledgebase">https://www.tableau.com/ko-kr/support/knowledgebase</a></p>
</blockquote>
<blockquote>
<p>🥕 <strong>커스터마이징 적용 사례</strong>:
<a href="https://brunch.co.kr/@cheonmyung/21">https://brunch.co.kr/@cheonmyung/21</a></p>
</blockquote>
<br/>
<br/>

<h2 id="라이센스--비용">&gt; 라이센스 / 비용</h2>
<h3 id="▶︎-라이센스-종류">▶︎ 라이센스 종류</h3>
<ul>
<li>Tableau Viewer</li>
<li>Tableau Explorer</li>
<li>Tableau Creator </li>
</ul>
<p><img src="https://images.velog.io/images/max-sum/post/6356bb35-c14b-48ad-b421-3c94b837acc4/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-22%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.17.24.png" alt=""></p>
<p>2017년 maintenance에서 정책변화가 있었고 이후 공식홈페이지에서는 구독형으로의 요금정책만 확인 가능합니다.</p>
<blockquote>
<p>🥕 <strong>서비스 이용로 정책변경 관련 기사</strong>:
<a href="https://www.geekwire.com/2017/tableau-software-continues-move-to-subscription-model-releases-new-prices-for-data-visualization-products/">https://www.geekwire.com/2017/tableau-software-continues-move-to-subscription-model-releases-new-prices-for-data-visualization-products/</a></p>
</blockquote>
<br/>

<h3 id="▶︎-라이센스별-요금정책">▶︎ 라이센스별 요금정책</h3>
<p>** 기본 적용 사항으로 배포시 하나 이상의 Creator가 필요</p>
<p><img src="https://images.velog.io/images/max-sum/post/1704a3d2-1ca7-4f45-8a6a-7ab94e7c8305/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.02.06.png" alt=""></p>
<ul>
<li>tableau online(tableau에서 호스팅)<ul>
<li>Tableau Viewer: 월 $15</li>
<li>Tableau Explorer: 월 $42</li>
<li>Tableau Creator: 월 $70</li>
<li><ul>
<li>리소스 블록(1개당): 월 $ 250</li>
</ul>
</li>
</ul>
</li>
</ul>
<blockquote>
<p>💡 <strong>리소스 블록</strong>:
Tableau Online의 계산 용량 단위이며 Tableau Prep Conductor 흐름을 실행합니다.
하나의 리소스 블록은 한 번에 하나의 흐름을 실행할 수 있으므로 동시에 실행할 수 있는 흐름 수는 리소스 블록의 수와 같습니다.</p>
</blockquote>
<br/>

<p><img src="https://images.velog.io/images/max-sum/post/1354b94b-7c30-4b2f-92c5-e6eec45e77fe/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.04.25.png" alt=""></p>
<ul>
<li><p>tableau server(on-premise or public cloud)</p>
<ul>
<li>Tableau Viewer: 월 $12</li>
<li>Tableau Explorer: 월 $35</li>
<li>Tableau Creator: 월 $70</li>
</ul>
</li>
<li><p>엔터프라이즈 요금제: 문의</p>
</li>
</ul>
<blockquote>
<p>🥕 <strong>컨설팅 업체를 통한 할인 사례(연구소)</strong>:
<a href="https://orgpsy.tistory.com/13">https://orgpsy.tistory.com/13</a></p>
</blockquote>
<blockquote>
<p>🥕 <strong>요금 출처</strong>:</p>
</blockquote>
<ul>
<li>유료: <a href="https://www.tableau.com/ko-kr/pricing/teams-orgs?_ga=2.63380271.1214400979.1647909340-1767330237.1647909340#server">https://www.tableau.com/ko-kr/pricing/teams-orgs?_ga=2.63380271.1214400979.1647909340-1767330237.1647909340#server</a><br/></li>
<li>요금계산/결재: <a href="https://buy.tableau.com/ko-kr/?gclid=CjwKCAjwxOCRBhA8EiwA0X8hixzE3N2QxS6UaZJvJCQUx3fhM-Nkjfhme3wn0TNhLhusQ3x6X3DEGxoCC_IQAvD_BwE&amp;gclsrc=aw.ds">https://buy.tableau.com/ko-kr/?gclid=CjwKCAjwxOCRBhA8EiwA0X8hixzE3N2QxS6UaZJvJCQUx3fhM-Nkjfhme3wn0TNhLhusQ3x6X3DEGxoCC_IQAvD_BwE&amp;gclsrc=aw.ds</a><br/></li>
<li>무료(학생용): <a href="https://www.tableau.com/ko-kr/academic/students">https://www.tableau.com/ko-kr/academic/students</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Data visualization tool | Grafana]]></title>
            <link>https://velog.io/@max-sum/Data-visualization-tool-Grafana</link>
            <guid>https://velog.io/@max-sum/Data-visualization-tool-Grafana</guid>
            <pubDate>Mon, 21 Mar 2022 14:47:47 GMT</pubDate>
            <description><![CDATA[<h2 id="grafana-소개와-특징">&gt; Grafana 소개와 특징</h2>
<h3 id="▶︎-data-visualization-tool">▶︎ data visualization tool</h3>
<p>시계열(time series, 일정 시간 간격으로 배치된 데이터들의 수열) 매트릭 데이터를 시각화한 대시보드를 제공해주는 오픈소스 도구입니다.</p>
<blockquote>
<p>🥕 <strong>공식 홈페이지</strong>:
<a href="https://grafana.com/oss/grafana/">https://grafana.com/oss/grafana/</a></p>
</blockquote>
<br/>

<p><img src="https://images.velog.io/images/max-sum/post/c298a4f2-1566-42e0-b336-2040f981b4ab/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-21%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.49.28.png" alt=""></p>
<p>하나의 화면에 다양한 데이터들을 시각화 할 수 있으므로 한눈에 직관적으로 원하는 데이터들을 관찰할 수 있고 사용자별 권한부여도 가능합니다.</p>
<h3 id="▶︎-장점">▶︎ 장점</h3>
<p>원하는 대로 자신만의 대시보드를 만들 수 있는 고도의 사용자 정의가 가능하며 온라인에서 사용할 수 있는 플러그인이 많이 있습니다. </p>
<p>적용 대상과 관련하여 MySQL, PostgreSQL와 같은 서버 리소스의 metric 정보를 비롯하여 데이터 검색/분석 엔진인 ElasticSearch의 log 데이터, AWS CloudWatch같은 cloud data source 까지 다양한 대상의 데이터를 시각화할 수 있습니다.</p>
<p>화면 분할을 통해 다른 시간대의 데이터간 비교, 라벨 필터를 이용한 빠른 로그검색과 애드혹(ad hoc)이라는 자동 적용 필터를 바로 만들 수도 있습니다.</p>
<p>지정한 수치에 도달하는 경우에 slack, VictorOps 등의 메신저와 연동하여 알람기능을 제공할 수도 있으며 클릭만으로 손쉽게 그래프를 그릴 수 있습니다. </p>
<p>추가로 상용 데이터 시각화 툴인 DataDog는 일정 주기를 두고 데이터를 직접 저장하여 시각화하므로 10분 이상의 시차가 발생하는데,
이와 관련하여 일부 무료로 사용 가능한 Garafana cloud는 외부 데이터 소스를 정의하여 쿼리를 통해 데이터를 동적으로 가져와 시각화하기 때문에 대시보드를 조회하는 동안 최신 데이터를 확인할 수 있습니다.</p>
<h3 id="▶︎-단점">▶︎ 단점</h3>
<p>처음에 커스텀 대시보드와 같은 시각화와 관련하여 원하는 결과물을 생성하기 위해 JASON 언어를 배워야 하는 등 어느정도 진입 장벽이 있습니다.</p>
<p>비교를 위해 단일 패널에 여러 날짜/시간 그래프를 설정하는 기능이 없습니다.</p>
<p>자체 데이터 저장소가 아니므로 여러 데이터 유형 간의 상관 관계를 처리하는 기능이 제한되어 있어서 여러 소스의 데이터를 집계하는 기본 기능이 없는 제한이 있습니다.</p>
<br/>

<blockquote>
<p>🥕 <strong>visualizations</strong>:
<a href="https://play.grafana.org/d/000000012/grafana-play-home?orgId=1">https://play.grafana.org/d/000000012/grafana-play-home?orgId=1</a></p>
</blockquote>
<br/>
<br/>

<h2 id="지원-데이터-소스">&gt; 지원 데이터 소스</h2>
<p>공식 홈페이지에 표기된 Supported data sources는 17종으로 세부 목록은 다음과 같습니다.</p>
<ul>
<li>Alertmanager</li>
<li>AWS CloudWatch</li>
<li>Azure Monitor</li>
<li>Elasticsearch</li>
<li>Google Cloud Monitoring</li>
<li>Graphite</li>
<li>InfluxDB</li>
<li>Loki</li>
<li>Microsoft SQL Server(MSSQL)</li>
<li>MySQL</li>
<li>OpenTSDB</li>
<li>PostgreSQL</li>
<li>Prometheus</li>
<li>Jaeger</li>
<li>Zipkin</li>
<li>Tempo</li>
<li>Testdata</li>
</ul>
<blockquote>
<p>🥕 <strong>출처</strong>:
<a href="https://grafana.com/docs/grafana/latest/datasources/#supported-data-sources">https://grafana.com/docs/grafana/latest/datasources/#supported-data-sources</a></p>
</blockquote>
<br/>
<br/>

<h2 id="표현-양식-종류">&gt; 표현 양식 종류</h2>
<p><img src="https://images.velog.io/images/max-sum/post/adbcc063-eab1-4f63-8e7c-e71439a93cb4/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.53.32.png" alt=""></p>
<p>기본 표현 양식은 18종으로 구성되어 있습니다.</p>
<blockquote>
<p>🥕 <strong>데이터 표현 양식</strong>
<a href="https://grafana.com/docs/grafana/latest/visualizations/">https://grafana.com/docs/grafana/latest/visualizations/</a></p>
</blockquote>
<br/>

<p><img src="https://images.velog.io/images/max-sum/post/aa8976da-8ad5-48e9-8f9b-c92bf28ff8bb/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-21%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2011.26.13.png" alt=""></p>
<p>커뮤니티가 활성화 되어 있고 다른 사용자들이 만든 수 많은 형태의 공유 가능한 대시보드들이 존재합니다.</p>
<blockquote>
<p>🥕 <strong>대시보드 공유 페이지</strong>:
<a href="https://grafana.com/grafana/dashboards/">https://grafana.com/grafana/dashboards/</a></p>
</blockquote>
<br/>
<br/>

<h2 id="커스터마이징--개발-용이성">&gt; 커스터마이징 / 개발 용이성</h2>
<p><img src="https://images.velog.io/images/max-sum/post/6901d2bd-058e-4aa0-a414-a1e384506216/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-21%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2011.54.42.png" alt=""></p>
<p>플러그인을 통한 기능확장 및 사용자 임의 커스터마이징이 가능하며 이미 만들어놓은 대시보드들을 자유롭게 import하여 사용할 수 있습니다.</p>
<p>따라서 시간을 들여 커스터마이징 하지 않더라도 적절한 대시보드를 찾기가 수월한 편으로 데이터 시각화 처리를 좀더 손쉽게 할 수 있습니다.</p>
<blockquote>
<p>🥕 <strong>Extend Grafana Plugins</strong>: 
<a href="https://grafana.com/grafana/plugins/?orderBy=weight&amp;direction=asc">https://grafana.com/grafana/plugins/?orderBy=weight&amp;direction=asc</a></p>
</blockquote>
<br/>
<br/>

<h2 id="라이센스--비용">&gt; 라이센스 / 비용</h2>
<h3 id="▶︎-라이센스-변경과-소스코드-오픈-문제">▶︎ 라이센스 변경과 소스코드 오픈 문제</h3>
<p>Grafana의 기본적인 라이센스 종류는 다음과 같습니다.</p>
<ul>
<li>Open source</li>
<li>Cloud</li>
<li>Enterprise</li>
</ul>
<br/>

<p>❗️Grafana open source의 라이센스는 2021년 4월을 기준으로 Apache-2.0에서 AGPL-3.0으로 변경되으며 이에 따라 인지해야할 변동사항으로는</p>
<ul>
<li>자유로운 사용은 가능하되 SaaS를 포함하여 네트워크로 서비스를 연결하는 클라이언트에게 소스코드를 공개해야함.(기존 GPL 라이센스는 SaaS 등으로 서비스하여도 배포로 보지 않고 소스 공개의무 없음)</li>
<li>기존 플러그인 등 일부는 Apache v2.0을 그대로 유지함.(소스오픈 불필요)</li>
</ul>
<blockquote>
<p>🥕 <strong>라이센스 변경사항 관련</strong>:
<a href="https://tech.kakao.com/2021/09/08/opensource-license/">https://tech.kakao.com/2021/09/08/opensource-license/</a></p>
</blockquote>
<br/>

<p>AGPL 적용 대상인데 소스코드 공개가 불가한 경우 결국 Grafana cloud / enterprise와 같은 유료버전을 사용해야 합니다.</p>
<blockquote>
<p>🥕 <strong>AGPLv3.0 적용 대상 소스코드 공개 불가 관련</strong>:
<a href="https://blog.outsider.ne.kr/1555">https://blog.outsider.ne.kr/1555</a></p>
</blockquote>
<br/>

<h3 id="▶︎-라이센스별-요금정책">▶︎ 라이센스별 요금정책</h3>
<p><img src="https://images.velog.io/images/max-sum/post/ac73c0ee-d793-46be-b3e2-a196591c6e87/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-21%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2011.22.30.png" alt=""></p>
<ul>
<li>Grafana open source: 무료</li>
<li>Grafana cloud: <ul>
<li>무료: 10,000개의 metric + 50GB log + 50GB trace</li>
<li>pro: 15,000개의 metric + 100GB log + 100GB trace 월 $49 + 추가사용량에 따른 금액 증가</li>
</ul>
</li>
<li>Grafana enterprise: 맞춤가격(문의)</li>
</ul>
<blockquote>
<p>🥕 <strong>요금 출처</strong>:
<a href="https://grafana.com/pricing/">https://grafana.com/pricing/</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Algorithm | sort - bubble]]></title>
            <link>https://velog.io/@max-sum/Algorithm-sort-bubble</link>
            <guid>https://velog.io/@max-sum/Algorithm-sort-bubble</guid>
            <pubDate>Mon, 28 Feb 2022 13:07:17 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&gt; 문제</h2>
<p>배열을 오름차순으로 정렬하는 문제입니다.</p>
<p>[7, 9, 2, 1, 3]의 배열이 주어진다면 [1, 2, 3, 7, 9]를 리턴하면 됩니다.</p>
<hr>
<br/>

<h2 id="solution1">&gt; solution1</h2>
<p>오름차순 sorting을 예시로 배열의 0번 idx와 1번 idx를 비교 후 0번이 더 큰 경우 둘을 swap해 주고 아니면 swap하지 않습니다.</p>
<p>그 다음은 1번 idx와 2번 idx를 비교하는 식으로 배열의 끝 까지 반복합니다.</p>
<p>최초 한 번의 순회를 마쳤다면 우선 배열의 마지막은 가장 큰 수가 위치해 있게 되고 다음 순회 시에 비교할 필요가 없어집니다.</p>
<p>이렇게 반복하면 끝에서부터 가장 큰 수부터 정렬이 되고 마지막에 idx 0과 idx 1을 비교한 후 sorting이 종료됩니다.</p>
<p>time complexity는 O(n)이 필요한 동작이 총 n번 반복이 되므로 O(n²)이 되며 bubble sorting은 평균적으로 O(n²)을 가지기 때문에 속도가 느립니다.</p>
<p>또다른 bubble sorting 특징으로는 stable solting이라는 점입니다.</p>
<p>[[7,&#39;a&#39;], [7,&#39;b&#39;], [5,&#39;a&#39;], [5,&#39;b&#39;], [3,&#39;c&#39;]]를 bubble sorting하면 [[3, &#39;c&#39;], [5, &#39;a&#39;], [5, &#39;b&#39;], [7, &#39;a&#39;], [7, &#39;b&#39;]]와 같이 stability하게 정렬됩니다.</p>
<p>qick sorting의 경우 stable하지 않게 정렬됩니다.</p>
<p>배열의 처음부터 끝가지 앞 뒤 두개의 숫자를 비교해가며 이동하는 모습이
마치 비누방울이 위로 떠올라가는 모습과도 비슷합니다.</p>
<h3 id="▶︎-code">▶︎ code</h3>
<pre><code class="language-py">from typing import List


nums_arr = [7, 9, 2, 1, 3]

def sort(nums: List[int]) -&gt; List[int]:
    for idx in range(0, len(nums) -1):
        for i in range(0, len(nums) -idx -1):
            if nums[i] &gt; nums[i +1]:
                nums[i], nums[i +1] = nums[i +1], nums[i]
    return nums

print(sort(nums_arr))

print(&#39;------------------&#39;)

complex_arr = [[7,&#39;a&#39;], [7,&#39;b&#39;], [5,&#39;a&#39;], [5,&#39;b&#39;], [3,&#39;c&#39;]]

def stable_sort(arr):
    for idx in range(0, len(arr) -1):
        for i in range(0, len(arr) -idx -1):
            if arr[i][0] &gt; arr[i +1][0]:
                arr[i], arr[i +1] = arr[i +1], arr[i]

    return arr

print(stable_sort(complex_arr))</code></pre>
<hr>
<br/>
<br/>
<br/>


<p>출처: 코드없는 프로그래밍</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[algorithm | array - sorted 2d matrix]]></title>
            <link>https://velog.io/@max-sum/algorithm-array-sorted-2d-matrix</link>
            <guid>https://velog.io/@max-sum/algorithm-array-sorted-2d-matrix</guid>
            <pubDate>Mon, 28 Feb 2022 12:44:16 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&gt; 문제</h2>
<p>아래와 같은 2중 배열에서 특정 숫자를 찾는 문제입니다.</p>
<p>[[1,3,5,7], 
    [2,8,11,12], 
    [4,9,14,19], 
    [6,15,25,40]]</p>
<hr>
<br/>


<h2 id="solution">&gt; solution</h2>
<p>문제의 경우 각 행은 좌에서 우로, 각 열은 위에서 아래로 커지는 패턴을 알 수 있습니다.</p>
<p>따라서 첫 행의 마지막 위치부터 탐색을 시작할 경우에 찾고자 하는 숫자가 
행의 마지막 숫자보다 크다면 해당 행은 모두 탐색할 필요가 없고 
다음 행으로 이동하면 됩니다.</p>
<p>만약 찾는 숫자가 기준점의 숫자보다 작다면 기준점 위로는 앞서 말한 과정을 거쳤거나 
첫 행이므로 탐색이 필요 없고,아래로는 기준점보다 큰 수이기 때문에 탐색이 필요 없어지므로 
기준점이 위치한 열은 모두 탐색할 필요 없이 기준점보다 작은 수가 위치한 왼쪽으로 이동하면 됩니다.</p>
<h3 id="▶︎-code">▶︎ code</h3>
<pre><code class="language-py">matrix = [
    [1,3,5,7], 
    [2,8,11,12], 
    [4,9,14,19], 
    [6,15,25,40]
]
target_num = 6

def matrix_travel(nums, target):
    row_count = len(nums[0])
    col_count = len(nums)

    pivot_row_idx = row_count - 1
    pivot_col_idx = 0

    for _ in range(row_count + col_count - 1):
        if (pivot_row_idx &lt; 0 or pivot_col_idx &lt; 0) or (pivot_row_idx &gt;= row_count or pivot_col_idx &gt;= col_count): #idx가 배열을 넘으면(찾는 숫자가 없으면) 종료
            return - 1

        if nums[pivot_row_idx][pivot_col_idx] == target:
            return [pivot_row_idx, pivot_col_idx]

        elif nums[pivot_row_idx][pivot_col_idx] &lt; target:
            pivot_col_idx += 1

        else:
            pivot_row_idx -= 1

print(matrix_travel(matrix, target_num))</code></pre>
<hr>
<br/>
<br/>
<br/>


<p>출처: 코드없는 프로그래밍</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[algorithm | array - merge intervals]]></title>
            <link>https://velog.io/@max-sum/algorithm-array-merge-intervals</link>
            <guid>https://velog.io/@max-sum/algorithm-array-merge-intervals</guid>
            <pubDate>Tue, 15 Feb 2022 15:56:51 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&gt; 문제</h2>
<p><img src="https://images.velog.io/images/max-sum/post/57062d52-8cfc-468f-9661-0965df11cadf/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-15%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2011.43.00.png" alt=""></p>
<p>위와 같이 시작점과 끝점이 있는 인터벌들이 들어있는 배열이 있습니다.</p>
<p>1<del>5까지의 인터벌이 있고 3</del>7까지의 인터벌이 있다면 1~5에 3이 포함되므로 둘은 [1, 7]로 merge가 됩니다.</p>
<p>1<del>7은 10</del>15를 포함하지 않으므로 둘은 merge되지 않습니다.</p>
<p>10<del>15과 8</del>16의 경우 10~15에 8이 포함되므로 merge됩니다.</p>
<p>이러한 방식을 반복하며 [[1, 7], [8, 16]]을 최종 리턴하면 됩니다.</p>
<hr>
<br/>
<br/>

<h2 id="solution1">&gt; solution1</h2>
<p><img src="https://images.velog.io/images/max-sum/post/1e7a62a0-44f2-4804-aa1f-bc18b03e0eac/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-16%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.24.34.png" alt=""></p>
<p>우선 merge를 할 때마다 이전에 merge된 배열과 비교를 반복하는 경우 O(n²)가 되게 됩니다.</p>
<p>더 좋은 방법을 찾아야 합니다.</p>
<hr>
<br/>
<br/>

<h2 id="solution2">&gt; solution2</h2>
<p><img src="https://images.velog.io/images/max-sum/post/6ea27948-0b33-4bf3-a4e6-12bf37006c17/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-16%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.16.17.png" alt=""></p>
<p>배열 요소들의 index 0을 기준으로 sorting해줍니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/53a06794-1d10-4c7d-b836-6d9aa2dc0b93/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-16%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.26.34.png" alt=""></p>
<p>대조하는 요소들 중 n번째 요소의 index 1이 n+1번째 요소의 index0보다 크다는 것은 n번째 요소에 n+1번째 요소가 포함된다는 의미이므로 merge 대상임을 알 수 있습니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/d790dbb2-1eb0-41a0-a71c-9c5491aeaec0/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-16%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.29.01.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/9f693b0e-2bff-4536-94d7-b52812538a2f/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-16%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.31.43.png" alt=""></p>
<p>두 대상 중 index 1이 더 큰 쪽의 값을 index 1로 넣으면 merge가 완료됩니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/788c51ac-ac32-4129-998d-26b8fd7a8c52/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-16%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.34.35.png" alt=""></p>
<p>이후 1<del>7과 8</del>16을 비교했을 때 1~7에 8이 포함되지 않기 때문에 merge가 되지 않는다는 것을 알 수 있습니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/1917bc8c-055d-4fdb-88bc-1ede98d76b53/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-16%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.40.07.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/2dc7ff54-bdce-4f28-b185-421ff40e7dd6/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-16%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.43.18.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/2e1404f6-5a28-47d0-b31d-f196d7d584e2/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-16%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.44.35.png" alt=""></p>
<p>다시 n번째 요소의 index 1과 n+1번째 요소의 index 0을 비교하여 포함 관계이므로 merge를 합니다.</p>
<p>처음에 sorting을 통해 정렬을 해 놓으므로 이미 이전에 merge된 요소와 merge 대상이 아님을 알기 때문에 다시 비교할 필요 없이 operation이 종료됩니다.</p>
<p>시간복잡도는 sorting O(n log n) + merge O(n)이 됩니다.</p>
<br/>

<h3 id="▶︎-code">▶︎ code</h3>
<pre><code class="language-py"># 규칙: 2차원 배열 중 n번째 배열 안에 n+1번째 배열의 값이 포함되면 merge, 아니면 저장

arr = [[8, 16], [1, 5], [10, 15], [3, 7]]

def merge_intervals(values):
    values.sort(key=lambda x:x[0]) # 0번째 index 기준 오름차순 정렬

    last_idx_0 = values[0][0]
    last_idx_1 = values[0][1]
    merged = []

    for idx_0, idx_1 in values[1:]:
        if last_idx_1 &gt;= idx_0:                 # n번째 배열값에 n+1번째 배열의 0번째 값이 포함되는 경우 merge
            last_idx_1 = max(idx_1, last_idx_1) # index 1 중 가장 큰 값을 저장

        else:
            result = [last_idx_0, last_idx_1]   # n번째 배열값에 n+1번째 배열의 0번째 값이 포함되지 않는 경우 not merge
            merged.append(result)               # 더이상 merge 대상이 아니므로 값 그대로 저장

            last_idx_0 = idx_0                  # n+1번째 배열의 값들이 새로운 기준이 됨
            last_idx_1 = idx_1

    result = [last_idx_0, last_idx_1]           # 최종 값은 비교 대상이 없으므로 저장 후 operation 종료
    merged.append(result)

    return merged

print(merge_intervals(arr))</code></pre>
<br/>

<h3 id="▶︎-번외">▶︎ 번외</h3>
<p> values.sort(key=lambda x:x[0]) 따라해보기</p>
<pre><code class="language-py">  def sort_2d_arr(values):
    pointer = 0
    idx = 1
    while pointer &lt; len(values):
        while idx &lt; len(values):
            if values[pointer][0] &gt; values[idx][0]:
                values[pointer], values[idx] = values[idx], values[pointer]
            idx += 1
        pointer += 1
        idx = pointer + 1
    print(&#39;values::&#39;, values)</code></pre>
<br/>
<br/>
<br/>


<p>출처: 코드없는 프로그래밍</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[algorithm | array - find peak element]]></title>
            <link>https://velog.io/@max-sum/algorithm-array-find-peak-element</link>
            <guid>https://velog.io/@max-sum/algorithm-array-find-peak-element</guid>
            <pubDate>Tue, 15 Feb 2022 09:25:26 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&gt; 문제</h2>
<p><img src="https://images.velog.io/images/max-sum/post/a86ad1dc-b61b-45ba-b7ad-5007f5d721e7/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-15%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.48.20.png" alt=""></p>
<p>주어진 배열에서 특정 index를 기준으로 양측의 수보다 큰(예외: 마지막 숫자의 경우 왼쪽의 숫자와만 비교) 숫자 중 가장 큰 수의 index를 리턴하는 문제입니다.</p>
<hr>
<br/>
<br/>

<h2 id="solution">&gt; solution</h2>
<p>주어진 문제의 경우 중간 index를 기준으로 오른쪽에 큰 값이 있기 때문에 binary search로 다음과 같이 해결할 수 있습니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/49488fd6-6ee7-496f-b830-39318d9ddcee/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-15%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.12.37.png" alt=""></p>
<p>시작을 기준으로
&quot;left_reading&quot;은 index 0을 가리킵니다.
&quot;right_reading&quot;은 배열의 가장 끝 index를 가리킵니다.
&quot;pivot&quot;은 left_reading와 right_reading의 중간 index를 가리킵니다.</p>
<p>pivot이 위치한 index의 값보다 pivot의 오른쪽 index가 가리키는 값이 &quot;크면&quot; left_reading을 pivot +1 해주고, &quot;작으면&quot; right_reading을 pivot의 index와 같게 해주는 것이 한 번의 동작입니다.</p>
<p>right_reading의 index가 left_reading의 index보다 클 때 까지 반복합니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/d1f9a3b2-b38a-4208-8bc5-3ef1bf4bfcb6/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-15%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.16.22.png" alt=""></p>
<p>pivot 오른쪽의 값이 pivot보다 크기 때문에 &quot;left_reading&quot;을 pivot의 오른쪽으로 이동시켜줍니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/8087fca5-c3a3-4e40-8bac-16f29109007c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-15%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.17.57.png" alt=""></p>
<p>&quot;pivot&quot;은 left_reading와 right_reading의 중간 index로 이동합니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/bef26ac9-353e-471b-a8d0-fe9cb8067204/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-15%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.21.08.png" alt=""></p>
<p>&quot;pivot&quot;의 오른쪽 값이 &quot;pivot&quot;이 위치한 값보다 작기 때문에 &quot;right_reading&quot;은 &quot;pivot&quot;의 위치로 이동합니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/77d7d4ea-6872-4ba7-8c84-0ecb275b1a77/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-15%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.22.14.png" alt=""></p>
<p>&quot;pivot&quot;은 다시 left_reading와 right_reading의 중간 index로 이동합니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/f131f786-21e7-4044-ae7a-f3cf41f1e140/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-15%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.52.20.png" alt=""></p>
<p>&quot;pivot&quot;의 다음 값이 &quot;pivot&quot;이 가리키는 값보다 크기 때문에 &quot;left_reading&quot;은 &quot;pivot&quot;의 다음 자리로 이동합니다.</p>
<p>&quot;right_reading&quot;의 index가 &quot;left_reading&quot;의 index와 같아지면서 최종 값으로 &quot;left_reading&quot;을 리턴하며 operation은 종료됩니다.</p>
<p>&quot;left_reading&quot;도 &quot;right_reading&quot;도 결국 마지막에 가장 큰 값을 가리키기 때문에 둘 중 어느 것을 리턴해도 상관 없습니다.</p>
<p>time complexity는 O(log n)입니다.</p>
<br/>

<h3 id="▶︎-code">▶︎ code</h3>
<pre><code class="language-py">arr = [1, 3, 2, 4, 5, 7, 6]

def find_peak_element(nums):
    left_reading = 0
    right_reading = len(nums) - 1

    if len(nums) &lt;= 1:
        return 0

    while left_reading &lt; right_reading:
        pivot = (left_reading + right_reading) // 2
        num = nums[pivot]
        next_num = nums[pivot + 1]

        if num &lt; next_num:
            left_reading = pivot + 1
        else:
            right_reading = pivot

    return left_reading

print(find_peak_element(arr))</code></pre>
<hr>
<br/>
<br/>
<br/>


<p>출처: 코드없는 프로그래밍</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[algorithm | array - merge sorted array]]></title>
            <link>https://velog.io/@max-sum/algorithm-array-merge-sorted-array</link>
            <guid>https://velog.io/@max-sum/algorithm-array-merge-sorted-array</guid>
            <pubDate>Mon, 14 Feb 2022 14:21:26 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&gt; 문제</h2>
<p><img src="https://images.velog.io/images/max-sum/post/041cf11b-b628-4437-b218-11f43296bd03/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.15.51.png" alt=""></p>
<p>두 개의 정렬된 배열이 있고 배열 1에 배열 2를 합쳐 정렬된 배열 1을 만드는 문제입니다.</p>
<p>배열 1에는 배열 2만큼의 빈 공간이 마련되어 있습니다.(예제에서는 0으로 표현)</p>
<p>그리고 m, n으로 각각의 배열이 가지고 있는 숫자의 갯수 정보가 있습니다.</p>
<hr>
<br/>
<br/>

<h2 id="solution1">&gt; solution1</h2>
<p>배열 1의 숫자를 모두 뒤로 미루고 2개의 index로 배열 1과 2를 비교해가며 작은 숫자부터 채워 넣는 방식입니다.</p>
<p>하지만 배열 1의 숫자를 뒤로 미루는 작업을 해야만 합니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/86dcc275-c89e-448e-b8ef-1aa95bb6507a/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.17.08.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/abfe25c6-e3af-44de-ba57-ecc4ad2739c9/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.17.56.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/484bed9e-1b4d-40e8-a209-557aa1d6b59f/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.18.14.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/5f0b51ea-8fbc-43f4-b1e9-df49fa6a7cec/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.18.31.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/ba24c2cc-a21f-4ba1-9429-df193981f172/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.18.49.png" alt=""></p>
<hr>
<br/>
<br/>

<h2 id="solution2">&gt; solution2</h2>
<p><img src="https://images.velog.io/images/max-sum/post/28de471f-b3fe-4c2d-b20b-4db8d4617c13/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.27.13.png" alt=""></p>
<p>reading index가 될 두 개의 포인터를 각 배열의 가장 큰 수를 가리키도록 하고 writing index가 될 또 하나의 포인터를 배열1의 가장 끝을 가리키도록 합니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/bc172ca0-040e-431b-adad-ba5991d794ab/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.29.03.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/00ff5481-5167-4cf3-925f-b10626d5ccda/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.31.27.png" alt=""></p>
<p>pin_b와 pin_c를 비교하여 큰 수인 pin_c를 pin_a에 넣고 pin_c와 pin_a를 좌측으로 한칸씩 이동합니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/49f0ca03-9c80-4274-9150-f7324b65b3df/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.32.28.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/29fc360a-423f-45f8-a8ec-c96972bc3492/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.32.49.png" alt=""></p>
<p>다시 pin_b와 pin_c를 비교하여 큰 수인 pin_b를 pin_a에 넣고 pin_b와 pin_a를 좌측으로 이동하는 패턴을 반복합니다.</p>
<p>time complexity는 배열1과 배열2의 pin이 index 0까지 이동하는데 걸리는 시간인 O(n+m)이 됩니다.</p>
<p>index로 접근하는 사고방식의 중요함을 기억해야겠습니다.</p>
<br/>

<h3 id="▶︎-code">▶︎ code</h3>
<pre><code class="language-py">arr1 = [1, 3, 5, 0, 0, 0]
count1 = 3

arr2 = [2, 4, 8]
count2 = 3

def merge_sorted_array(nums1, m, nums2, n):
    reading_idx_1 = m - 1
    reading_idx_2 = n - 1
    writing_idx = len(nums1) - 1

    if reading_idx_2 &lt; 0: # arr2가 빈 배열인 경우
        return

    while 0 &lt;= reading_idx_1 and 0 &lt;= reading_idx_2:
        num1 = nums1[reading_idx_1]
        num2 = nums2[reading_idx_2]

        if num1 &gt;= num2:
            nums1[writing_idx] = num1
            reading_idx_1 -= 1
            writing_idx -= 1
        else:
            nums1[writing_idx] = num2
            reading_idx_2 -= 1
            writing_idx -= 1

    # case:: arr1 = [5, 6, 7, 0, 0, 0] / arr2 = [1, 2, 3]
    while 0 &lt;= reading_idx_2:
        num = nums2[reading_idx_2]
        nums1[writing_idx] = num
        reading_idx_2 -= 1
        writing_idx -= 1

merge_sorted_array(arr1, count1, arr2, count2)
print(arr1)</code></pre>
<hr>
<br/>
<br/>
<br/>

<p>출처: 코드없는 프로그래밍</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[algorithm | array - sort colors]]></title>
            <link>https://velog.io/@max-sum/algorithm-array-sort-colors</link>
            <guid>https://velog.io/@max-sum/algorithm-array-sort-colors</guid>
            <pubDate>Mon, 14 Feb 2022 12:39:40 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&gt; 문제</h2>
<p><img src="https://images.velog.io/images/max-sum/post/22fcf1ff-684e-4510-b434-d9b5aceaf6eb/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.37.31.png" alt=""></p>
<p>위와 같은 배열이 있는 경우 작은 수 부터 큰 수 순서로 정렬하여야 합니다.</p>
<hr>
<br/>
<br/>

<h2 id="solution1_count">&gt; solution1_count</h2>
<p>3개의 빈 변수를 만들어 오른쪽으로 옮겨가며 각 숫자의 갯수를 기록한 후 output으로 각각의 갯수만큼 차례대로 채운 배열을 리턴하면 됩니다.</p>
<p>time complexity는 O(n)가 됩니다.</p>
<hr>
<br/>
<br/>

<h2 id="solution2_sort-colors">&gt; solution2_sort colors</h2>
<p>in-place swap방식</p>
<p>3개의 포인터를 만들어 다음과 같은 규칙을 정해줍니다.
&#39;A 포인터는 0을 받으면 오른 쪽으로 한 칸&#39;
&#39;B 포인터는 2를 받으면 왼쪽으로 한 칸&#39;
&#39;C 포인터는 오른쪽으로 이동하면서 0을 만나면 A포인터와 swap, 2를 만나면 B포인터와 swap합니다.&#39;</p>
<p><img src="https://images.velog.io/images/max-sum/post/29a1d44d-7e4a-410f-8f62-b2b6c5508ed8/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.32.24.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/9063313f-cc17-4bc0-a96d-b91295ed892a/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.32.50.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/b438d8e7-d835-48fb-9e63-49ef3f16bf65/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.33.10.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/ee40151c-0605-49ac-be9c-0f89e6dfa63c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.36.06.png" alt=""></p>
<p>C 포인터가 0을 만났기 때문에 A 포인터가 가리키는 숫자와 스왑을 합니다.
그리고 A 포인터와 B 포인터는 오른쪽으로 한 칸 이동합니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/8c1a4443-1907-4fc9-8226-6c85ce014eed/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.36.52.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/ee11086e-b634-4bdc-bb25-2b2c79efc802/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.37.05.png" alt=""></p>
<p>C 포인터가 B 포인터와 스왑을 한 경우 A 포인터와의 스왑과는 달리 C 포인터가 가리키는 숫자는 0, 1, 2 모두 가능하므로 스왑 후의 값을 다시 한 번 체크해줘야 함을 주의해야 합니다.</p>
<p>C 포인터가 1을 가리키는 경우 스왑 없이 오른쪽으로 이동합니다.</p>
<p>위와 같은 과정을 반복하면 왼쪽부터 0 ~ 2의 순서로 정렬되며 최종적으로 C 포인터와 B 포인터가 교차(C &lt;= B)되면 operation이 종료 되도록 합니다.</p>
<p>time complexity는 O(n)이 됩니다.</p>
<p>Quick sort의 원리와 다를 바 없으며 partitioning에 대한 내용입니다.</p>
<br/>

<h3 id="▶︎-code">▶︎ code</h3>
<pre><code class="language-py">nums = [1, 0, 2, 2, 0, 1, 2, 1, 0]

def sort_colors(arr):
    a_pointer = 0
    b_pointer = len(arr) - 1
    c_pointer = 0

    while c_pointer &lt;= b_pointer:
        print(&#39;check loop_top:::&#39;, &#39;arr:&#39;, arr, &#39;/&#39;, &#39;c_pointer:&#39;, c_pointer)
        if arr[c_pointer] == 0:
            arr[a_pointer], arr[c_pointer] = arr[c_pointer], arr[a_pointer]
            a_pointer += 1
            c_pointer += 1
        elif arr[c_pointer] == 2:
            arr[c_pointer], arr[b_pointer] = arr[b_pointer], arr[c_pointer]
            b_pointer -= 1
        else: # arr[c_pointer] == 1
            c_pointer += 1
        print(&#39;check loop_bot:::&#39;, &#39;arr:&#39;, arr, &#39;/&#39;, &#39;c_pointer:&#39;, c_pointer)

print(sort_colors(nums))
print(f&#39;result: {nums}&#39;)</code></pre>
<hr>
<br/>
<br/>
<br/>

<p>출처: 코드없는 프로그래밍</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[algorithm | array - find pivot index]]></title>
            <link>https://velog.io/@max-sum/algorithm-array-find-pivot-index</link>
            <guid>https://velog.io/@max-sum/algorithm-array-find-pivot-index</guid>
            <pubDate>Sun, 13 Feb 2022 08:08:41 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&gt; 문제</h2>
<p>배열의 element들 중 특정 값의 왼쪽에 있는 숫자들의 합과 오른쪽에 있는 합이 같을 때 그 숫자를 pivot이라 하고 pivot의 인덱스를 리턴하는 문제입니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/669f3888-d698-4941-9bfb-30bf1e2d1635/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.27.40.png" alt=""></p>
<p>위와 같은 경우 9의 왼쪽의 element들의 합은 11이고 오른쪽 element들의 합은 11이기 때문에 9는 pivot이 되고 index 3이 리턴됩니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/5550de8d-2c1b-46d8-808f-68d99db1b8f1/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.31.05.png" alt=""></p>
<p>위 배열의 경우 pivot이 존재할 수 없고 -1을 리턴하면 정답이 됩니다.</p>
<hr>
<br/>
<br/>

<h2 id="solution1_brute-force">&gt; solution1_brute force</h2>
<p>완전탐색 알고리즘을 생각해볼 수 있습니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/2426cb00-75d0-4427-84da-2aea38a46ab0/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.41.21.png" alt=""></p>
<p>예시와 같이 처음에 8을 기준으로 오른쪽의 숫자들을 더해줍니다.(O(n))</p>
<br/>

<p><img src="https://images.velog.io/images/max-sum/post/c1dd0382-b503-4296-b650-50009a2d3307/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.43.06.png" alt=""></p>
<p>이후 기준을 옮기고 좌 우의 숫자들을 각각 더합니다(O(n) + O(n))</p>
<p>이렇게 계속 진행하면 O(n)*n이 되기 때문에 O(n²)의 time complexity가 됩니다.</p>
<p>더 좋은 방법을 생각해야 합니다.</p>
<hr>
<br/>
<br/>

<h2 id="solution2_sliding-window">&gt; solution2_sliding window</h2>
<p><img src="https://images.velog.io/images/max-sum/post/c4250f37-8fa4-49e0-98b9-95685015e855/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.50.09.png" alt=""></p>
<p>전체 합계를 구합니다.(O(n))</p>
<p>전체합계 = 31</p>
<br/>

<p><img src="https://images.velog.io/images/max-sum/post/4ddb6abc-e44d-485c-b2e1-b83f4f4c0ed5/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.53.29.png" alt=""></p>
<p>8을 pivot으로 잡았다면 전체합계에서 8을 빼줍니다.</p>
<p>전체(오른쪽)합계 = 31 - 8</p>
<p>아직 pivot 왼쪽의 합계는 0입니다.</p>
<br/>

<p><img src="https://images.velog.io/images/max-sum/post/40d3301b-a401-4cae-9473-daa3f1ad2a4d/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.58.24.png" alt=""></p>
<p>pivot이 오른쪽으로 이동하고 pivot은 2가 되었습니다.</p>
<p>전체(오른쪽)합계 = 31 - 8 - 2</p>
<p>왼쪽 합계에 이전 pivot이었던 8을 더해줍니다.</p>
<p>왼쪽합계 = 0 + 8</p>
<br/>

<p>이와 같은 방식으로 pivot이 이동하며 좌•우의 값들을 더하고 빼며 pivot index를 찾아나가게 됩니다.</p>
<p>pivot이 한 번 이동할 때 필요한 계산량은 O(1)이고 총 n개의 pivot이 있으므로 o(n)의 time complexity가 필요하고 맨 처음 전체합계를 한 O(n)까지 총 O(n)으로 array 갯수에 linear한 time complexity를 갖습니다.</p>
<br/>

<h3 id="▶︎-code">▶︎ code</h3>
<pre><code class="language-py">array = [8, 2, 1, 9, 3, 6, 2]

def find_pivot_index(values):
    total_sum = sum(values)
    left_sum = 0
    right_sum = total_sum

    past_pivot = 0
    for i in range(len(array)):
        pivot = values[i]
        right_sum = right_sum - pivot
        left_sum = left_sum + past_pivot

        if left_sum == right_sum:
            return i

        past_pivot = pivot

    return -1

print(f&#39;The index of pivot is {find_pivot_index(array)}&#39;)</code></pre>
<hr>
<br/>
<br/>
<br/>

<p>출처: 코드없는 프로그래밍</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[algorithm | array - move zeroes]]></title>
            <link>https://velog.io/@max-sum/algorithm-array-move-zeroes</link>
            <guid>https://velog.io/@max-sum/algorithm-array-move-zeroes</guid>
            <pubDate>Sat, 12 Feb 2022 06:47:12 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">&gt; 문제</h2>
<p><img src="https://images.velog.io/images/max-sum/post/b0cf4c5e-a56c-4e97-aa68-ff4c7459eda0/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.16.55.png" alt=""></p>
<p>배열의 element중 값이 0인 경우 위와 같이 배열의 뒤로 보내고 기존 숫자들의 순서는 유지하는 알고리즘입니다.</p>
<p>0을 찾아 맨 끝으로 보내고 맨 끝에 있는 수를 앞으로 한칸씩 움직여서 그 0의 자리로 보낼 수도 있지만 operation이 복잡해집니다.</p>
<p>또는 0을 찾아서 한칸씩 bubble swap을 시킬 수 있지만 0을 찾을 때마다 bubble swap을 한다는 것은 너무 많은 operation이 발생하고 time complexity는 O(n * #0)가 됩니다.</p>
<hr>
<br/>
<br/>

<h2 id="solution1_swap">&gt; solution1_swap</h2>
<p><img src="https://images.velog.io/images/max-sum/post/71429ce3-f90f-4ea4-b8e2-d9d7ceeb7374/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.07.03.png" alt=""></p>
<p>&#39;0이 아닌 수를 찾는 index&#39;와 &#39;항상 0을 가리키는 index&#39;를 정의합니다.
둘 모두의 첫 index는 0입니다.
(&#39;항상 0을 가리키는 index&#39;라는 이름이 약간 헷갈리기도 하네요)</p>
<br/>

<p><img src="https://images.velog.io/images/max-sum/post/7831b072-d805-4224-8c9e-dcca72044874/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.58.29.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/ba82744c-e9a7-462f-9a62-c62fb9fabaee/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.59.07.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/020fd018-69b1-48de-9dc8-49f47591337d/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.15.08.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/412d960b-a3ab-4c09-abd0-62b9c538d6ec/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.20.04.png" alt=""></p>
<p>&#39;0이 아닌 수를 찾는 index&#39;가 한칸씩 오른쪽으로 이동하다가 0이 아닌 수를 찾으면 0과 swap을 하고 &#39;항상 0을 가리키는 index&#39;를 1칸 오른쪽으로 옮겨줍니다.</p>
<p>(예시처럼 시작 부분의 숫자가 0이 아닌 경우 둘은 swap이 일어나지만 표면적인 변화는 없으며, &#39;항상 0을 가리키는 index&#39;는 1칸 옮겨지게 됩니다.)</p>
<p><img src="https://images.velog.io/images/max-sum/post/777e6f20-3600-4198-b162-351e993464d2/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.18.36.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/76007ffa-88b0-4eed-973f-27c5042ecd4e/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.22.49.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/6c60095f-d43e-4f10-b29e-0d5220254886/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.23.43.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/c8ed2b18-ee95-444c-97a0-3eafc7a7c5d2/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.24.35.png" alt=""></p>
<p>&#39;0이 아닌 수를 찾는 index&#39;의 루프가 끝나면서 최종 완료됩니다.</p>
<br/>

<h3 id="▶︎-code">▶︎ code</h3>
<pre><code class="language-py">array = [3, 9, 0, 1, 0, 29, 30]

def move_zero(values):
    zero_location = 0
    for i in range(len(values)):
        if values[i] != 0:
            values[zero_location], values[i] = values[i], values[zero_location]
            zero_location += 1

    return values

print(move_zero(array))</code></pre>
<hr>
<br/>
<br/>

<h2 id="solution2_copy">&gt; solution2_copy</h2>
<p>&#39;0이 아닌 수를 찾는 index&#39;와 &#39;항상 0을 가리키는 index&#39;를 정의합니다.
둘 모두의 첫 index는 0입니다.
(swap과 마찬가지로 &#39;항상 0을 가리키는 index&#39;라는 이름이 알맞지는 않는 것 같습니다.)</p>
<p><img src="https://images.velog.io/images/max-sum/post/775fb650-9a4c-4469-8e7c-dc548a1c6a5a/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.18.42.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/d6a39ed8-8f98-486e-b98f-157be00a54d3/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.12.36.png" alt=""></p>
<p>&#39;0이 아닌 수를 찾는 index&#39;가 0이 아닌 수를 만나면 그 값을 복사하여 &#39;항상 0을 가리키는 index&#39;에 있는 값을 해당 값으로 변경시킵니다.</p>
<p>위와 같은 경우 표면적으로는 변화가 없지만 0이 아닌 수를 만났기 때문에 해당 인덱스의 값은 실재로 복사되어 대체되었습니다.</p>
<br/>

<p><img src="https://images.velog.io/images/max-sum/post/4ff971bc-739f-4ca0-8ae1-271d0ddc71c5/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.23.36.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/965f1034-cdb8-4aba-8e01-dc5ff359ee19/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.07.51.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/7e2bd627-1be3-4d5a-8536-de59d3535c32/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.22.28.png" alt=""></p>
<p>&#39;0이 아닌 수를 찾는 index&#39;가 0이 아닌 수를 만나면 해당 값을 복사하여 &#39;항상 0을 가리키는 index&#39;가 가리키는 0을 대체합니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/1ada5e7a-0ad1-411b-8929-0d296fdeef7e/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.26.11.png" alt=""></p>
<p>이후 &#39;항상 0을 가리키는 index&#39;는 오른 쪽으로 한칸 옮겨지게 되고 &#39;0이 아닌 수를 찾는 index&#39;는 다시 0이 아닌 숫자를 찾아 이동하고 복사/대체를 반복합니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/ff0345e3-9c63-477e-b1e9-bfef7df38b52/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.28.29.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/384f1b34-6848-467c-9421-ba55b5ca4481/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.28.57.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/17985ca8-4258-4ada-a75e-3a2df2a19a5e/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.31.38.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/78e77e74-941a-4701-9f4f-8aeaab1e7594/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.35.03.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/06ab4495-0cee-43ea-892a-c028800afb0e/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.35.18.png" alt=""></p>
<p>&#39;0이 아닌 수를 찾는 index&#39;의 루프가 끝나면 &#39;항상 0을 가리키는 index&#39;가 가리키는 위치부터 배열의 끝 까지 0을 덮어 써주면 최종 완료됩니다.</p>
<h3 id="▶︎-code-1">▶︎ code</h3>
<pre><code class="language-py">array = [3, 9, 0, 1, 0, 29, 30]

def move_zero(values):
    zero_location = 0
    for i in range(len(values)):
        if values[i] != 0:
            values[zero_location] = values[i]
            zero_location += 1

    while zero_location &lt; len(values):
        values[zero_location] = 0
        zero_location += 1

    return values

print(move_zero(array))</code></pre>
<hr>
<br/>
<br/>
<br/>

<p>출처: 코드없는 프로그래밍</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[algorithm | array - binary search]]></title>
            <link>https://velog.io/@max-sum/algorithm-binary-search</link>
            <guid>https://velog.io/@max-sum/algorithm-binary-search</guid>
            <pubDate>Fri, 11 Feb 2022 14:55:08 GMT</pubDate>
            <description><![CDATA[<h2 id="동작원리">&gt; 동작원리</h2>
<p>배열이 정렬되어 있을 때 특정 element를 찾아달라는 문제입니다.</p>
<p>O(logn)의 time complexity를 가집니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/f670aa61-204f-445b-848e-afae94f08bf3/123.003.jpeg" alt=""></p>
<br/>

<p>위와 같은 배열이 있는 경우 Left는 첫 인덱스를, Right는 끝 인덱스를 가리키며 Pivot은 Left+Right/2의 인덱스에 위치합니다.</p>
<p>이 때 22라는 숫자를 찾을 경우 Pivot을 기준으로 오른쪽에 위치한다는 것을 확인하게 됩니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/4e440a2a-784f-43f8-a9c9-a04898b125b3/111111.001.jpeg" alt=""></p>
<br/>

<p>이후 left는 기존 pivot의 인덱스보다 +1 된 곳으로 이동되며 pivot은 다시 left와 right의 중간으로 이동하게 됩니다.</p>
<p>그러면 우리가 찾고자 했던 22에 pivot이 위치하게 되었으므로 pivot을 리턴해 주게 됩니다.</p>
<p>grande말입니다.</p>
<p>만약 우리가 찾으려던 숫자가 위 배열에는 없는 23일 경우라면 어떻게 될까요?</p>
<br/>

<p><img src="https://images.velog.io/images/max-sum/post/ccaf7f6f-528d-49e6-87b3-840fa93609d2/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-11%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2011.09.48.png" alt=""></p>
<p>23은 22보다 크기 때문에 left의 인덱스는 22에 있는 pivot보다 앞에 있는 30으로 이동합니다.</p>
<p>그리고 pivot 또한 30으로 이동합니다.</p>
<br/>

<p><img src="https://images.velog.io/images/max-sum/post/46033ed6-2c10-4c95-b06c-17f3b0f68071/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-11%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2011.19.07.png" alt=""></p>
<p>하지만 30은 우리가 찾는 23보다 크기 때문에 이번에는 right가 pivot보다 1 작은 인덱스로 이동합니다.</p>
<p>그리고 left와 right의 위치가 바뀌면서 우리가 찾는 23이 없다는 정보(-1)를 리턴하면서 알고리즘을 종료합니다.</p>
<hr>
<br/>
<br/>

<h2 id="example-code">&gt; example code</h2>
<pre><code class="language-python">array = [1, 2, 5, 9, 15, 22, 30]

my_number = int(input(&#39;찾으려는 숫자를 입력하세요.: &#39;))

def binary_search(arr, target):
    left = 0
    right = len(arr) -1

    while left &lt;= right:
        pivot = (left+right) // 2

        if arr[pivot] == target:
            return pivot
        elif arr[pivot] &lt; target:
            left = pivot + 1
        else: # arr[pivot] &gt; target
            right = pivot - 1

    return -1

print(f&#39;입력한 숫자의 index는 {binary_search(array, my_number)}입니다.&#39;)</code></pre>
<hr>
<br/>
<br/>
<br/>

<p>출처: 코드없는 프로그래밍</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[algorithm | array 기본]]></title>
            <link>https://velog.io/@max-sum/algorithm-array-basic</link>
            <guid>https://velog.io/@max-sum/algorithm-array-basic</guid>
            <pubDate>Fri, 11 Feb 2022 09:25:22 GMT</pubDate>
            <description><![CDATA[<h2 id="array와-algorithm">&gt; Array와 algorithm</h2>
<h3 id="▶︎-stable-unstable">▶︎ stable, unstable</h3>
<p>Array와 관련된 문제는 대부분 sorting(heap, quick, merge)과 관련이 있습니다.</p>
<p>time complexity는 O(nlogn)을 가집니다.</p>
<p>stable한 algorithm에는 merge가, unstable한 algorithm에는 quick과 heap이 있습니다.</p>
<p>stalble sort의 경우 다음과 같이 이름 또한 일관성 있게 정렬됩니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/e4767325-a42a-4945-8681-d4cca6843d65/yesi.002.jpeg" alt=""></p>
<br/>

<p>unstalble sort는 이름에 대한 정렬은 일관성이 없습니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/bad4f379-9326-4026-8e70-8ba647907824/yesi.001.jpeg" alt=""></p>
<br/>
<br/>

<h3 id="▶︎-search-binary-search">▶︎ search, binary search</h3>
<p><img src="https://images.velog.io/images/max-sum/post/e3f2ed8f-e262-487a-b5d6-e29917bbe2c5/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-02-11%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.16.04.png" alt=""></p>
<p>search의 time complexity는 배열의 element를 순회해야 하므로 O(n)을 가집니다.</p>
<p>만약 배열이 정렬이 되어있는 경우라면 binary search를 사용할 수 있고 time complexity는 O(logn)을 가집니다.</p>
<p>이 두가지가 array의 기본 operation이고 graph와 같은 2차원, 다차원 배열 문제가 나오기도 합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[MySQL | 문법_2. 숫자와 문자열 관련 함수]]></title>
            <link>https://velog.io/@max-sum/MySQL-%EB%AC%B8%EB%B2%952.-%ED%95%A8%EC%88%98-%EA%B7%B8%EB%A3%B9</link>
            <guid>https://velog.io/@max-sum/MySQL-%EB%AC%B8%EB%B2%952.-%ED%95%A8%EC%88%98-%EA%B7%B8%EB%A3%B9</guid>
            <pubDate>Wed, 29 Dec 2021 12:44:27 GMT</pubDate>
            <description><![CDATA[<p>💡 <a href="https://velog.io/@max-sum/MySQL-syntax1#%EF%B8%8E-%ED%8F%AC%ED%95%A8-%EC%9C%A0%EB%AC%B4-%EC%97%B0%EC%82%B0%EC%9E%90-between-in">MySQL | 문법_1. 데이터 가져오기, 연산자</a></p>
<h2 id="숫자를-다루는-함수들">&gt; 숫자를 다루는 함수들</h2>
<h3 id="▶︎-반올림-올림-내림">▶︎ 반올림, 올림, 내림</h3>
<p>🌈 <strong>SELECT</strong> <strong>ROUND</strong>(0.5), <strong>CEIL</strong>(0.2), <strong>FLOOR</strong>(0.5);</p>
<ul>
<li>ROUND() : 반올림</li>
<li>CEIL() : 올림</li>
<li>FLOOR() : 내림
<img src="https://images.velog.io/images/max-sum/post/e1e1a589-66ed-411c-a362-84e57182268e/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.27.51.png" alt=""></li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> Price <strong>ROUND</strong>(Price), <strong>CEIL</strong>(Price), <strong>FLOOR</strong>(Price) <strong>FROM</strong> Products;</p>
<ul>
<li>매개변수로 원하는 column을 넣기만 하면 알아서 연산해줍니다.
<img src="https://images.velog.io/images/max-sum/post/728c5d36-a803-4745-83b9-0ce37ccf9a2b/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.33.38.png" alt=""></li>
</ul>
<br/>

<h3 id="▶︎-절대값양수로-변환하기">▶︎ 절대값(양수로 변환하기)</h3>
<p>🌈 <strong>SELECT</strong> <strong>ABS</strong>(10), <strong>ABS</strong>(-10.5), <strong>ABS</strong>(10 - 110);</p>
<ul>
<li>음수를 양수로 변환해줍니다.
<img src="https://images.velog.io/images/max-sum/post/c371fda5-8f77-4827-b266-6929d33dcd80/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.38.26.png" alt=""></li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> OrderDetails <strong>WHERE</strong> <strong>ABS</strong>(Quantity - 5) <strong>&lt;</strong> 5;</p>
<ul>
<li><p>Quantity 컬럼의 값이 4 ~ 9 사이의 값인 데이터만 출력됩니다.</p>
</li>
<li><p>4-5=1, 9-5=4이기 때문에 5보다 작은 수가 되어 TRUE가 되기 때문입니다.
<img src="https://images.velog.io/images/max-sum/post/8721c7e9-0d5a-4183-a209-cdbc2bc97d2b/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.46.47.png" alt=""></p>
</li>
</ul>
<br/>

<h3 id="▶︎-여러-colume중에-가장-큰작은-값-가져오기">▶︎ 여러 colume중에 가장 큰/작은 값 가져오기</h3>
<p>🌈 <strong>SELECT</strong> <strong>GREATEST(1, 5, 10)</strong>, <strong>LEAST(1, 5, 10)</strong>;</p>
<p><img src="https://images.velog.io/images/max-sum/post/bfbd4b95-74fe-4c74-a090-07da64a8f824/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.49.01.png" alt=""></p>
<br/>

<p>🌈 <strong>SELECT</strong> OrderDetailID, Quantity, <strong>GREATEST</strong>(Quantity, OrderDetailID), <strong>LEAST</strong>(Quantity, OrderDetailID) <strong>FROM</strong> OrderDetails;</p>
<ul>
<li>column끼리 비교하여 가장 큰/작은 값을 가져옵니다.
<img src="https://images.velog.io/images/max-sum/post/a9d8cba2-6039-45bc-85cc-3dc6d1946749/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.59.58.png" alt=""></li>
</ul>
<br/>

<h3 id="▶︎-하나의-column에서-가장-큰작은-값-가져오기">▶︎ 하나의 column에서 가장 큰/작은 값 가져오기</h3>
<p>🌈 <strong>SELECT</strong> <strong>MAX</strong>(Quantity), <strong>MIN</strong>(Quantity) <strong>FROM</strong> OrderDetails <strong>WHERE</strong> OrderDetailID <strong>BETWEEN</strong> 1 <strong>AND</strong> 20;</p>
<ul>
<li>OrderDetails 테이블의 OrderDetailID가 1 ~ 20인 데이터들 중에 Quantity column에서 가장 큰 값과 가장 작은 값을 구하였습니다.
<img src="https://images.velog.io/images/max-sum/post/02c3c5d4-2d7f-461f-ac6b-3aa39c49bca3/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.15.49.png" alt=""></li>
</ul>
<br/>

<h3 id="▶︎-갯수-총합-평균값-구하기">▶︎ 갯수, 총합, 평균값 구하기</h3>
<p>🌈 <strong>SELECT</strong> <strong>COUNT</strong>(Quantity), <strong>SUM</strong>(Quantity), AVG(Quantity) FROM OrderDetails WHERE OrderDetailID BETWEEN 1 AND 20;</p>
<ul>
<li>지정한 column의 갯수, 합계, 평균값을 구하였습니다.
<img src="https://images.velog.io/images/max-sum/post/105c7f58-251c-44af-96e9-a261e29ea8df/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.20.11.png" alt=""></li>
</ul>
<br/>

<h3 id="▶︎-제곱-제곱근-구하기">▶︎ 제곱, 제곱근 구하기</h3>
<p>🌈 <strong>SELECT</strong> <strong>POW</strong>(2, 3), <strong>POWER</strong>(2, 3), <strong>SQRT</strong>(16);</p>
<ul>
<li>POW(A, B), POWER(A, B)는 A를 B만큼 제곱해줍니다.</li>
<li>SQRT()는 제곱근(루트)을 구해줍니다.
<img src="https://images.velog.io/images/max-sum/post/a8ad04a9-691f-4ace-90d7-b20a80b1eca4/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.25.07.png" alt=""></li>
</ul>
<br/>

<h3 id="▶︎-소숫점-자리수-선택하기">▶︎ 소숫점 자리수 선택하기</h3>
<p>🌈 <strong>SELECT</strong> <strong>TRUNCATE</strong>(123.12345, 1), <strong>TRUNCATE</strong>(123.12345, 2), <strong>TRUNCATE</strong>(123.12345, 3);</p>
<ul>
<li><p>두 번째 매개변수 숫자만큼 소숫점 자리수를 가져옵니다.</p>
</li>
<li><p>반올림을 해주지는않습니다.
<img src="https://images.velog.io/images/max-sum/post/280cfbe4-a6c1-4223-a448-9f2aaab17302/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.30.48.png" alt=""></p>
</li>
<li><p>두 번째 매개변수에 음수가 들어가면 소숫점은 사라지고 그 숫자만큼 소숫점의 앞쪽 숫자들이 0이 됩니다.
<img src="https://images.velog.io/images/max-sum/post/5b8bc861-de2c-4cc8-b166-fe5605ec16d1/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.33.35.png" alt=""></p>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> Price <strong>FROM</strong> Products <strong>WHERE</strong> <strong>TRUNCATE</strong>(Price, 0) = 12;</p>
<ul>
<li>Products의 Price 컬럼에서 TRUNCATE로 소숫점을 제거한 값이 12인 경우만 구해오는 식입니다.
<img src="https://images.velog.io/images/max-sum/post/2c117111-ae06-4bd9-ac97-ba69e6dd6d6a/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.37.14.png" alt=""></li>
</ul>
<hr>
<br/>
<br/>

<h2 id="문자열을-다루는-함수">&gt; 문자열을 다루는 함수</h2>
<h3 id="▶︎-대소문자로-변환하기">▶︎ 대소문자로 변환하기</h3>
<p>🌈 <strong>SELECT</strong> <strong>UPPER</strong>(&#39;abcDEF&#39;), <strong>LOWER</strong>(&#39;abcDEF&#39;);</p>
<ul>
<li><p>UPPER(), UCASE() : 대문자로 바꿔줍니다.</p>
</li>
<li><p>LOWER(), LCASE() : 소문자로 바꿔줍니다.</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/max-sum/post/7428fdec-1dcb-4791-b3c0-6d3c9e65f668/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.40.17.png" alt=""></p>
<br/>

<p>🌈 <strong>SELECT</strong>  <strong>UPPER</strong>(CustomerName), <strong>LOWER</strong>(CustomerName) <strong>FROM</strong> Customers;</p>
<p><img src="https://images.velog.io/images/max-sum/post/6753b300-6932-408b-a95c-09de63403e35/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.42.07.png" alt=""></p>
<br/>

<h3 id="▶︎-문자열들-이어-붙이기">▶︎ 문자열들 이어 붙이기</h3>
<p>🌈 <strong>SELECT</strong> <strong>CONCAT</strong>(&#39;반가웠어요!&#39;, &#39; &#39;, &#39;그럼&#39;, 20000);</p>
<ul>
<li><p>CONCAT(..., ..., ...) : 괄호 안의 문자열들을 이어 붙여줍니다.</p>
</li>
<li><p>숫자가 끼어있어도 문자열로 변환되어 이어집니다.
<img src="https://images.velog.io/images/max-sum/post/f8ef9877-b710-4d6b-9241-c2c9a06e0a3a/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.48.53.png" alt=""></p>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> <strong>CONCAT</strong>(&#39;주문번호: &#39;, OrderID) <strong>FROM</strong> OrderDetails;</p>
<ul>
<li>구하는 값을 우리가 원하는 형식으로 변환해줄 수 있습니다.
<img src="https://images.velog.io/images/max-sum/post/29710436-484b-426c-8770-2253a3ca2085/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.55.16.png" alt=""></li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> <strong>CONCAT_WS</strong>(&#39;~&#39;, &#39;반가웠어요!&#39;, &#39;그럼&#39;, 20000);</p>
<ul>
<li>CONCAT_WS(S, ..., ...) : 매개변수 첫번째 자리인 S에 넣은 문자가 합치려는 문자들 사이에 들어가게 됩니다.
<img src="https://images.velog.io/images/max-sum/post/73691496-8606-4e05-805d-772f7596fc57/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.51.58.png" alt=""></li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> <strong>CONCAT_WS</strong>(&#39;-&#39;, FirstName, LastName) <strong>AS</strong> &#39;Full name&#39; <strong>FROM</strong> Employees;</p>
<ul>
<li>두 컬럼의 내용을 합쳐 값을 가져와 보았습니다.
<img src="https://images.velog.io/images/max-sum/post/ff67a45e-994e-4bac-9992-05a969c1d733/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.00.03.png" alt=""></li>
</ul>
<br/>

<h3 id="▶︎-문자열-잘라서-가져오기">▶︎ 문자열 잘라서 가져오기</h3>
<p>🌈 <strong>SELECT</strong> <strong>SUBSTR</strong>(&#39;123456&#39;, 3), <strong>SUBSTR</strong>(&#39;123456&#39;, 3, 2), <strong>SUBSTR</strong>(&#39;123456&#39;, -4), <strong>SUBSTR</strong>(&#39;123456&#39;, -4, 2);</p>
<ul>
<li><p>SUBSTR()는 인수를 3개 받을 수 있습니다.</p>
</li>
<li><p>첫번째 인수를 대상으로 두번째 인수의 수 만큼 왼쪽에서 오른쪽으로 센 후 뒤의 문자를 가져옵니다.</p>
</li>
<li><p>두번째 인수가 음수인 경우 문자의 뒤(오른쪽) 끝에서부터 셈을 합니다.</p>
</li>
<li><p>세번째 인수는 가져올 글자 수를 지정합니다.</p>
</li>
<li><p>❗️MySQL은 숫자를 1부터 셉니다.</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/max-sum/post/e60cf2e0-e551-4c89-b67a-2341ce0b20bb/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.12.31.png" alt=""></p>
<br/>

<p>🌈 <strong>SELECT</strong> <strong>LEFT</strong>(&#39;123456&#39;, 3), <strong>RIGHT</strong>(&#39;123456&#39;, 3);</p>
<ul>
<li><p>LEFT() : 왼쪽에서부터 두번째 인자에 적힌 수 만큼 글자를 가져옵니다.</p>
</li>
<li><p>RIGHT() : 오른쪽에서부터 글자를 가져옵니다.
<img src="https://images.velog.io/images/max-sum/post/3306aa9d-aaad-4d06-9ea6-f8e6f1c47e6c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.04.20.png" alt=""></p>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> OrderDate, <strong>LEFT</strong>(OrderDate, 4) <strong>AS</strong> &#39;Year&#39;, <strong>SUBSTR</strong>(OrderDate, 6, 2) <strong>AS</strong> &#39;Month&#39;, <strong>RIGHT</strong>(OrderDate, 2) <strong>AS</strong> &#39;Day&#39; <strong>FROM</strong> Orders;</p>
<ul>
<li>SUBSTR(), LEFT(), RIGHT() 각각의 특징을 이용해 다음과 같이 날짜 컬럼을 나눌 수도 있습니다.</li>
</ul>
<p><img src="https://images.velog.io/images/max-sum/post/8b9a8ad8-3359-461f-be2c-e19b2010f9dd/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.18.05.png" alt=""></p>
<br/>

<h3 id="▶︎-문자-길이-확인하기">▶︎ 문자 길이 확인하기</h3>
<p>🌈 <strong>SELECT</strong> <strong>LENGTH</strong>(&#39;반가워요&#39;), <strong>CHAR_LENGTH</strong>(&#39;반가워요&#39;);</p>
<ul>
<li><p>LENGTH() : 문자열의 바이트 길이를 출력합니다.</p>
</li>
<li><p>CHAR_LENGTH() : 문자열의 문자 갯수를 출력합니다.</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/max-sum/post/7644e9ef-7ddb-4472-9f7d-742281a74a8f/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.15.58.png" alt=""></p>
<br/>

<h3 id="▶︎-글자-양쪽의-공백-제거하기">▶︎ 글자 양쪽의 공백 제거하기</h3>
<p>🌈 <strong>SELECT</strong> <strong>CONCAT</strong>(&#39;H&#39;, &#39;   OLL   &#39;, &#39;A&#39;), <strong>CONCAT</strong>(&#39;H&#39;, <strong>TRIM</strong>(&#39;   OLL   &#39;), &#39;A&#39;), <strong>CONCAT</strong>(&#39;H&#39;, <strong>LTRIM</strong>(&#39;   OLL   &#39;), &#39;A&#39;), <strong>CONCAT</strong>(&#39;H&#39;, <strong>RTRIM</strong>(&#39;   OLL   &#39;), &#39;A&#39;);</p>
<ul>
<li><p>TRIM() : 문자 양쪽 끝의 공백을 모두 제거해줍니다.</p>
</li>
<li><p>LTRIM(), RTRIM() : 각각 문자의 왼쪽, 오른쪽 공백을 제거해줍니다.</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/max-sum/post/37968de4-dee9-4a50-a0a0-4f42b80fb3e2/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.22.08.png" alt=""></p>
<br/>

<p>🌈 <strong>SELECT</strong>  * <strong>FROM</strong> Categories <strong>WHERE</strong> CategoryName = <strong>TRIM</strong>(&#39;   Condiments&#39;);</p>
<ul>
<li>검색할 때 스페이스를 붙이고 검색할 수도 있는데 이럴 경우 공백에 의해 다른 문자로 인식되어 찾으려는 데이터가 검색되지 않게 되므로 이런 상황에서 사용합니다.
<img src="https://images.velog.io/images/max-sum/post/77a67acb-add1-4a8d-a4a6-462496bfb52a/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.30.50.png" alt=""></li>
</ul>
<br/>

<h3 id="▶︎-특정한-문자-이어붙이기">▶︎ 특정한 문자 이어붙이기</h3>
<p>🌈 <strong>SELECT</strong> <strong>LPAD</strong>(&#39;ABC&#39;, 5, &#39;^&#39;), <strong>RPAD</strong>(&#39;ABC&#39;, 5, &#39;^&#39;);</p>
<ul>
<li><p>1번째 인자로 넣은 문자가 2번째 인자의 길이만큼 될 때 까지 3번째 인자에 넣은 문자를 이어붙여줍니다.</p>
</li>
<li><p>LPAD() : 1번 문자의 왼쪽에 붙여줍니다.</p>
</li>
<li><p>RPAD() : 1번 문자의 오른쪽에 붙여줍니다.
<img src="https://images.velog.io/images/max-sum/post/c0298adb-cbf3-417b-a487-f06d5b281e80/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.37.32.png" alt=""></p>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> ProductID, <strong>LPAD</strong>(ProductID, 5, 0), Price, <strong>RPAD</strong>(Price, 6, 0) <strong>FROM</strong> Products;</p>
<ul>
<li>서로 다른 길이의 문자 자릿수를 맞춰줄 수 있습니다.
<img src="https://images.velog.io/images/max-sum/post/02fd8ac9-677c-43ff-8d24-718308bebf10/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.43.59.png" alt=""></li>
</ul>
<br/>

<h3 id="▶︎-특정-문자-대체하기">▶︎ 특정 문자 대체하기</h3>
<p>🌈 <strong>SELECT</strong> <strong>REPLACE</strong>(&#39;동대문에서 동대문닭한마리를 먹었습니다.&#39;, &#39;동대문&#39;, &#39;인사동&#39;);</p>
<ul>
<li>REPLACE() : 1번째 인자를 대상으로 2번째 인자의 문자와 같은 문자를 3번째 인자의 문자로 바꿔줍니다.
<img src="https://images.velog.io/images/max-sum/post/50106bcf-db2c-4b32-9fca-22e2617805b9/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.47.34.png" alt=""></li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> CustomerName, <strong>REPLACE</strong>(CustomerName, &#39; &#39;, &#39;⭐️&#39;) <strong>FROM</strong> Customers;</p>
<ul>
<li>이름 사이 공백을 ⭐️로 대체하였습니다.
<img src="https://images.velog.io/images/max-sum/post/53a80aa5-cd34-46c4-83ae-e4847cec6fc5/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.53.50.png" alt=""></li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> Description, REPLACE(Description, &#39;and&#39;, &#39;,&#39;), REPLACE(Description, &#39;,&#39;, &#39;and&#39;) FROM Categories;</p>
<ul>
<li><p>함수를 여러번 사용하여 문제를 해결할 수도 있습니다.</p>
</li>
<li><p>Description 컬럼에서 콤마 대신 and를 사용하고 싶은데 기존에 입력된 값 중에 콤마 대신 and가 되어 있는 부분이 있는 경우</p>
</li>
<li><p>첫번째 REPLACE()로 and를 콤마로 바꾼 후 두번째 REPLACE()로 다시 콤마를 and로 바꿔서 문제를 해결할 수 있습니다.</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/max-sum/post/16f2c3fc-aa63-4cf2-9563-8965950cc162/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.04.44.png" alt=""></p>
<br/>

<h3 id="▶︎-찾는-문자의-자릿수-가져오기">▶︎ 찾는 문자의 자릿수 가져오기</h3>
<p>🌈 <strong>SELECT</strong> <strong>INSTR</strong>(&#39;12345&#39;, &#39;123&#39;), <strong>INSTR</strong>(&#39;12345&#39;, &#39;2345&#39;), <strong>INSTR</strong>(&#39;12345&#39;, 3), <strong>INSTR</strong>(&#39;12345&#39;, &#39;9&#39;);</p>
<ul>
<li><p>첫번째 인자에 두번째 인자가 동일하게 존재하는 경우 첫번째 자릿수를 반환해줍니다.</p>
</li>
<li><p>존재하지 않는 경우 0을 반환합니다.
<img src="https://images.velog.io/images/max-sum/post/60844644-70bb-4fc6-82f4-f06a883f5518/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.12.40.png" alt=""></p>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> * <strong>FROM</strong> Customers <strong>WHERE</strong> <strong>INSTR</strong>(CustomerName, &#39; &#39;) <strong>BETWEEN</strong> 1 <strong>AND</strong> 3;</p>
<ul>
<li>자릿&quot;수&quot;를 반환하므로 BETWEEN을 이용하여 이름에 공백이 들어가는 자릿수가 3 이하인 데이터가져올 수도 있습니다.</li>
</ul>
<p><img src="https://images.velog.io/images/max-sum/post/d253ea0e-d978-418f-82c5-48eb1ddea4d2/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.27.39.png" alt=""></p>
<br/>

<h3 id="▶︎-자료형-변환하기">▶︎ 자료형 변환하기</h3>
<p>🌈 <strong>SELECT</strong> &#39;01&#39; = &#39;1&#39;, <strong>CONVERT</strong>(&#39;01&#39;, DECIMAL) = <strong>CONVERT</strong>(&#39;1&#39;, DECIMAL);</p>
<ul>
<li><p>CONVERT(A, T) : A를 T의 자료형으로 변환해줍니다.</p>
</li>
<li><p>문자 &#39;01&#39;과 &#39;1&#39;은 다르기때문에 FALSE가 됩니다.</p>
</li>
<li><p>이 둘을 DECIMAL형으로 바꾸면 둘 다 숫자 1이 되므로 TRUE가 됩니다.
<img src="https://images.velog.io/images/max-sum/post/028330ff-9ec8-4c27-ae00-be66e2633c02/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.37.58.png" alt=""></p>
</li>
</ul>
<br/>
<br/>
<br/>


<p>💕 <strong>참고</strong>: 얄코님 유튜브 강의, SQL 첫걸음</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[MySQL | 문법_1. 데이터 가져오기, 연산자]]></title>
            <link>https://velog.io/@max-sum/MySQL-syntax1</link>
            <guid>https://velog.io/@max-sum/MySQL-syntax1</guid>
            <pubDate>Tue, 28 Dec 2021 12:59:45 GMT</pubDate>
            <description><![CDATA[<p>SQL 문법이 정리되지 않은 상태에서 ORM을 사용하여 DB를 다루다가
SQL 문법이 거의 그대로 쓰이는 typeORM의 query builder를 만나고
row query에 대해 정리하는 시간을 가져야겠다는 생각이 들었습니다.</p>
<p>또한 종종 문제 해결을 위해 raw query를 알고 있어야 할 때가 생기기도 하고
ORM이 방언이라 한다면 SQL은 표준어와 같은 느낌이라 예제에서 자주 접하게 되어
시간이 지날 수록 필수로 알고있어야 한다는 생각이 강렬하게 듭니다.</p>
<p>ORM들이 SQL 문법에 기초하여 만들어지기도 하고요.</p>
<p>&quot;SQL 첫걸음&quot;이라는 책을 1회독 한 후 정리한다는 느낌으로 작성하기 때문에
SQL에 대해 완전히 생소하신 분께는 친절하지 않은 글일 수 있습니다.</p>
<hr>
<br/>

<h2 id="데이터-가져오기">&gt; 데이터 가져오기</h2>
<p>🥕 <a href="https://www.w3schools.com/mysql/trymysql.asp?filename=trysql_select_all">예제 링크</a> </p>
<br/>
🌈 사전지식

<ul>
<li>SELECT: 테이블 안의 column을 지정</li>
<li>FROM  : 테이블을 지정</li>
<li>WHERE : 조건을 지정</li>
</ul>
<br/>

<h3 id="▶︎-select로-열column-다루기">▶︎ &quot;SELECT&quot;로 열(column) 다루기</h3>
<p>🌈 <strong>SELECT</strong> * <strong>FROM</strong> Custormers;</p>
<ul>
<li><p>SELECT 뒤에 나오는 *(asterisk)는 테이블의 모든 열(column)을 선택한다는 의미입니다.</p>
</li>
<li><p>FROM 뒤에는 선택하려는 테이블 이름입니다.</p>
</li>
<li><p>결과: 특정 테이블의 모든 column이 선택됩니다.</p>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> CustomerName <strong>From</strong> Customers;</p>
<ul>
<li><p>특정 column을 지정하려면 SELECT 뒤에 해당 colume 이름을 명시합니다.</p>
</li>
<li><p>결과: Customers 테이블에서 CustomerName 컬럼만 선택됩니다.</p>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> CustomerName, City, Country <strong>From</strong> Customers;</p>
<ul>
<li><p>SELECT 뒤에 여러개의 colume을 지정할 수도 있습니다.</p>
</li>
<li><p>column끼리의 구분은 comma(,)로 해줘야 합니다.</p>
</li>
<li><p>결과: Customers 테이블에서 CustomerName, City, Country colume이 선택됩니다.</p>
</li>
</ul>
<br/>


<p>🌈 <strong>SELECT</strong> CustomerName, 1, null, &#39;hi&#39; <strong>FROM</strong> Customers;</p>
<ul>
<li><p>Colume이 아닌 것들을 출력할 수도 있습니다.</p>
</li>
<li><p>CustomerName 뒤 1, null, &#39;hi&#39;은 자료형들을 표시한 것입니다.</p>
</li>
<li><p>결과: 각각 colume이 되어 출력됩니다.
<img src="https://images.velog.io/images/max-sum/post/bfb3c0c7-ac05-4669-a850-8f679b480750/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.37.35.png" alt=""></p>
</li>
</ul>
<br/>

<h3 id="▶︎-select로-행row-다루기">▶︎ &quot;SELECT&quot;로 행(row) 다루기</h3>
<p>🌈 <strong>SELECT</strong> * <strong>FROM</strong> Customers <strong>WHERE</strong> CustomerID = 1;</p>
<ul>
<li><p>Customers 테이블에서 CustomerID가 1인 데이터만 선택하려 합니다.</p>
</li>
<li><p>WHERE 뒤에 조건을 지정할 수 있습니다.</p>
</li>
<li><p>결과: CustomerID가 1인 행만 선택됩니다.</p>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> CustomerName, Country <strong>FROM</strong> Customers <strong>WHERE</strong> CustomerID = 1;</p>
<ul>
<li><p>SELECT 뒤에 원하는 Culomn만 선택해서 가져올 수 있습니다.</p>
</li>
<li><p>결과: CustomerID가 1인 행에서 CustomerName, Country만 선택됩니다.</p>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> * <strong>FROM</strong> Customers <strong>WHERE</strong> CustomerId &lt; 11;</p>
<ul>
<li>결과: CustomerID가 11보다 작은 row만 선택됩니다.(ID 1 ~ ID 10)</li>
</ul>
<br/>


<h3 id="▶︎-순서를-지정하여-데이터-가져오기">▶︎ 순서를 지정하여 데이터 가져오기</h3>
<p>🌈 <strong>SELECT</strong> * <strong>FROM</strong> OrderDetails <strong>ORDER BY</strong> ProductID <strong>DESC</strong>;</p>
<ul>
<li><p>ASC: 오름차순(ascending), 따로 지정하지 않으면 기본값으로 지정됩니다.</p>
</li>
<li><p>DESC : 내림차순(descending)</p>
</li>
<li><p>결과: OrderDetails 테이블의 ProductID를 기준으로 내림차순으로 정리됩니다.</p>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> * <strong>FROM</strong> OrderDetails <strong>ORDER BY</strong> ProductID, Quantity <strong>DESC</strong>;</p>
<ul>
<li><p>ORDER BY 뒤에 정렬하고 싶은 Column을 여러개 두어 먼저 정렬된 기준 안에서
또 다시 정렬을 할 수 있습니다.</p>
</li>
<li><p>순서는 먼저 작성된 column이 먼저 정렬된 후 먼저 정렬된 기준 안에서
다음에 작성된 기준에 따라 새롭게 정렬이 됩니다.</p>
</li>
<li><p>결과: OrderDetails 테이블의 ProductID가 먼저 오름차순으로 정리된 후에 
ProductID의 정렬기준 안에서 Quantity 기준으로 내림차순으로 정리됩니다.</p>
</li>
</ul>
<br/>

<h3 id="▶︎-필요한-갯수만큼-데이터-가져오기">▶︎ 필요한 갯수만큼 데이터 가져오기</h3>
<p>🌈 <strong>SELECT</strong> * <strong>FROM</strong> OrderDetails <strong>LIMIT</strong> 10;</p>
<ul>
<li><p>필요하지 않는 데이터까지 부르면 서버에 무리가 가고 성능이 저하되기 때문에 이를 방지하기 위하여 LIMIT을 사용합니다.</p>
</li>
<li><p>LIMIT 뒤에 원하는 데이터 row 갯수만큼의 숫자를 적어주면 됩니다.</p>
</li>
<li><p>결과: OrderDetails 테이블의 row 10개를 선택합니다.(1 ~ 10)</p>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> * <strong>FROM</strong> OrderDetails <strong>LIMIT</strong> 5, 10;</p>
<ul>
<li><p>LIMIT 뒤에 2개의 숫자를 넣으면 앞의 숫자만큼의 row를 건너뛴 후 10개의 row를 선택합니다.</p>
</li>
<li><p>게시판의 글 목록과 같이 페이지마다 보여줄 데이터를 구분할 때 사용합니다.</p>
</li>
<li><p>1페이지에서 10개의 글을 보여줬다면 2페이지에서는 앞의 10개의 글은 건너 뛰고 보여줘야하는데 이럴 때 사용합니다(pagenation)</p>
</li>
<li><p>결과: OrderDetails 테이블에서 5개의 row를 건너 뛴 다음 10개의 row를 선택합니다.(6 ~ 15)</p>
</li>
</ul>
<br/>

<h3 id="▶︎-column에-별명-붙여서-데이터-가져오기">▶︎ column에 별명 붙여서 데이터 가져오기</h3>
<p>🌈 <strong>SELECT</strong> CustomerName <strong>AS</strong> Name, ContactName <strong>AS</strong> NikcName <strong>FROM</strong> Customers;</p>
<ul>
<li><p>선택한 Column 이름에 별명(alias)을 붙여 불러올 수 있습니다.</p>
</li>
<li><p>SELECT의 column 이름 뒤에 AS를 붙이고 이어서 원하는 별명을 적으면 됩니다.</p>
</li>
<li><p>결과: CustomerName은 Name으로, ContactName은 NikcName으로 column 이름이 변경되어 선택됩니다.(영구적으로 column 이름이 변경되는 것은 아닙니다)</p>
</li>
</ul>
<br/>

<h3 id="▶︎-종합해보기">▶︎ 종합해보기</h3>
<pre><code class="language-sql">SELECT CustomerName AS &#39;고객명&#39;, City AS &#39;도시&#39;, Country AS &#39;국가&#39;
FROM Customers
WHERE City = &#39;London&#39; OR Country = &#39;UK&#39;
ORDER BY CustomerName
LIMIT 0, 5</code></pre>
<ul>
<li>해설<ul>
<li><strong>SELECT ~ AS</strong>로 CustomerName, City, Country의 별명 지정</li>
<li><strong>FROM</strong>으로 테이블 지정</li>
<li><strong>WHERE</strong>로 조건 지정</li>
<li><strong>ORDER BY</strong>로 CustomerName를 기준으로 순서 지정</li>
<li><strong>LIMIT</strong>으로 데이터 갯수 제한 지정</li>
</ul>
</li>
</ul>
<br/>

<br/>

<h2 id="연산자">&gt; 연산자</h2>
<h3 id="▶︎-사칙연산자">▶︎ 사칙연산자</h3>
<p>🌈 <strong>SELECT</strong> 1 + 2;</p>
<ul>
<li>사칙연산이 가능합니다.
<img src="https://images.velog.io/images/max-sum/post/da5aac29-1896-4242-a64e-cfa146720708/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.58.12.png" alt=""></li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> 5 - 2.5 <strong>AS</strong> &#39;사칙&#39;;</p>
<ul>
<li>별명도 붙여줄 수 있습니다.
<img src="https://images.velog.io/images/max-sum/post/6361eb32-28c0-4073-be43-74eb5c3892b4/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.00.03.png" alt=""></li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> 2 * (10 / 2) % 2 <strong>AS</strong> &#39;계산결과&#39;, &#39;열정맨&#39;;</p>
<ul>
<li>결과
<img src="https://images.velog.io/images/max-sum/post/112814b9-c06b-4241-bd10-f6d70d3ef1ae/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.02.38.png" alt=""></li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> &#39;하&#39; + 2 + &#39;!&#39;;</p>
<ul>
<li>문자열과 숫자를 더하면 문자는 0이 됩니다.
<img src="https://images.velog.io/images/max-sum/post/3ec3020f-8463-4c4e-b37e-25a0922d0378/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.04.23.png" alt=""></li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> &#39;1&#39; + 2;</p>
<ul>
<li>하지만 문자열이 숫자라면 숫자로 간주됩니다!
<img src="https://images.velog.io/images/max-sum/post/5998e21c-1641-4008-81fb-4c2ff59010fa/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.07.32.png" alt=""></li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> CustomerID, EmployeeID, CustomerID + EmployeeID <strong>FROM</strong> Orders;</p>
<ul>
<li>column끼리도 연산을 할 수 있습니다.
<img src="https://images.velog.io/images/max-sum/post/658066a8-be5f-4fdf-9134-69db48e60932/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.12.19.png" alt=""></li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> ProductID, Price, Price / 2 <strong>AS</strong> &#39;50% SalePrice&#39; <strong>FROM</strong> Products;</p>
<ul>
<li>할인가도 구할 수 있습니다!😃
<img src="https://images.velog.io/images/max-sum/post/82551d5b-393f-4f01-8d37-512059403c75/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.17.41.png" alt=""></li>
</ul>
<br/>

<h3 id="▶︎-true-false-연산">▶︎ TRUE, FALSE 연산</h3>
<p>🌈 <strong>SELECT</strong> FALSE, !TRUE, NOT 1, TRUE, !FALSE, NOT FALSE;</p>
<ul>
<li>MySQL에서의 true, false 판단은 다음과 같습니다.
<img src="https://images.velog.io/images/max-sum/post/2451e95f-c495-49c9-8675-3bd475124621/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.23.51.png" alt=""></li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> 0 = TRUE, 1 = FALSE, 1 = TRUE, 0 = FALSE;</p>
<ul>
<li>true는 1, false는 0으로 판단합니다.
<img src="https://images.velog.io/images/max-sum/post/e00d1316-450c-44f1-9f65-163253f27e95/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.30.41.png" alt=""></li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> * FROM Customers <strong>WHERE</strong> TRUE;</p>
<ul>
<li>모든 데이터를 다 가져옵니다.</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> * FROM Customers <strong>WHERE</strong> FALSE;</p>
<ul>
<li><p>아무 데이터도 가져오지 않습니다.</p>
</li>
<li><p>where 조건이 참인 경우만 데이터를 가져오는 것을 알 수 있습니다.</p>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> * <strong>FROM</strong> Customers <strong>WHERE</strong> Country = &#39;Germany&#39;;</p>
<ul>
<li>Country가 Germany인 값들만 TRUE가 되어 데이터를 가져옵니다.
<img src="https://images.velog.io/images/max-sum/post/70b158ec-4a37-43b6-8b25-6e7640815260/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.49.08.png" alt=""></li>
</ul>
<br/>


<h3 id="▶︎-is-is-not-연산자">▶︎ IS, IS NOT 연산자</h3>
<p>🌈 <strong>SELECT</strong> TRUE <strong>IS</strong> TRUE, TRUE <strong>IS NOT</strong> TRUE;</p>
<ul>
<li><p>IS: 양쪽이 모두 TRUE이거나 FALSE면 결과는 참이 됩니다.</p>
</li>
<li><p>IS NOT: 한쪽은 TRUE이고 한쪽은 FALSE면 결과는 참이 됩니다.
<img src="https://images.velog.io/images/max-sum/post/07fdc152-0ab5-4e56-966d-ca1ed223e1ac/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.53.42.png" alt=""></p>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> (TRUE <strong>IS</strong> TRUE) <strong>IS</strong> FALSE;</p>
<ul>
<li>괄호 안의 값이 참이고 이것을 거짓이라고 한다면 결과는 FALSE가 됩니다.
<img src="https://images.velog.io/images/max-sum/post/3d6d40b2-fb3c-4d94-b2a2-a589599875ef/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.58.25.png" alt=""></li>
</ul>
<br/>

<h3 id="▶︎-or-and-연산자">▶︎ OR, AND 연산자</h3>
<p>🌈 <strong>SELECT</strong> 1 + 1 = 2 <strong>OR</strong> 1 + 1 = 3;</p>
<ul>
<li><p>OR: 양쪽의 값 중 1개만 TRUE여도 결과는 TRUE가 됩니다.</p>
</li>
<li><p>따라서 결과는 TRUE가 됩니다.</p>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong>  1 + 1 = 2 <strong>AND</strong> 1 + 1 = 3;</p>
<ul>
<li><p>AND: 양쪽의 값 모두가 TRUE일 때 결과는 TRUE가 됩니다.</p>
</li>
<li><p>따라서 결과는 FALSE가 됩니다.</p>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> * <strong>FROM</strong> Customers <strong>WHERE</strong> City = &#39;Berlin&#39; <strong>AND</strong> Country = &#39;Germany&#39;;</p>
<ul>
<li>City가 Berlin&quot;이면서&quot; Country가 Germany인 값만 TRUE가 됩니다.
<img src="https://images.velog.io/images/max-sum/post/557d1eec-d68f-4a9c-a518-813fbdcf863d/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.06.56.png" alt=""></li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> * <strong>FROM</strong> Customers <strong>WHERE</strong> City = &#39;Berlin&#39; <strong>OR</strong> Country = &#39;Germany&#39;;</p>
<ul>
<li>City가 Berlin&quot;이거나&quot; Country가 Germany인 값만 TRUE가 됩니다.
<img src="https://images.velog.io/images/max-sum/post/04d4e80e-8263-4059-81e1-d7b02e816e13/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.07.52.png" alt=""></li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> * <strong>FROM</strong> Orders <strong>WHERE</strong> CustomerID = 65 <strong>AND</strong> (EmployeeID = 6 <strong>OR</strong> ShipperID = 2);</p>
<ul>
<li><p>CustomerID가 65&quot;이면서&quot;, (EmployeeID가 6&quot;이거나&quot; ShipperID가 2인 값)만 TRUE가 됩니다.
<img src="https://images.velog.io/images/max-sum/post/b30c22be-f3ca-4e87-9041-562910c9a1e3/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.15.33.png" alt=""></p>
</li>
<li><p>❗️괄호가 없다면 왼쪽부터 순서대로 연산하기 때문에 다른 결과가 나옵니다.</p>
<ul>
<li>CustomerID가 65&quot;이면서&quot; EmployeeID가 6&quot;이거나&quot;, ShipperID가 2인 값이 TRUE가 됩니다.</li>
</ul>
</li>
</ul>
<br/>

<h3 id="▶︎-대소관계-연산자">▶︎ 대소관계 연산자</h3>
<p>🌈 <strong>SELECT</strong> 1 = 1, 1 != 1, 1 &lt;&gt; 1, 1 &gt; 2, 1 &lt; 2, 1 &gt;= 2, 1 &lt;= 2; </p>
<ul>
<li><p>각 기호는 다음 조건일 때 TRUE가 됩니다.</p>
<ul>
<li><p>= : 양쪽값이 같을 때 </p>
</li>
<li><p>!=, &lt;&gt; : 양쪽 값이 다를 때</p>
</li>
<li><blockquote>
<p>: 왼쪽 값이 더 클 때</p>
</blockquote>
</li>
<li><p>&lt; : 오른쪽 값이 더 클 때</p>
</li>
<li><blockquote>
<p>= : 왼쪽 값이 더 크거가 양쪽의 값이 같을 때</p>
</blockquote>
</li>
<li><p>&lt;= : 오른쪽 값이 더 크거나 양쪽의 값이 같을 때</p>
<p><img src="https://images.velog.io/images/max-sum/post/1364d368-76d3-4b60-bbdd-fed00469314f/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.30.21.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> ProductName, Price, Price <strong>&gt;</strong> 20 <strong>AS</strong> &#39;20달러 넘음&#39; <strong>FROM</strong> Products;</p>
<ul>
<li>column에 비교연산을 사용하여 TRUE와 FALSE로 나눌 수 있습니다.
<img src="https://images.velog.io/images/max-sum/post/911ce048-a8e3-4463-aeaa-27767a8e35ad/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.35.51.png" alt=""></li>
</ul>
<br/>

<h3 id="▶︎-포함-유무-연산자-between-in">▶︎ 포함 유•무 연산자 BETWEEN, IN</h3>
<p>🌈 <strong>SELECT</strong> 10 <strong>BETWEEN</strong> 1 <strong>AND</strong> 10;</p>
<ul>
<li><p>10이 1과 10 사이에 있는 값이면 TRUE가 됩니다.</p>
</li>
<li><p>조건이 1과 10이라면 1과 10도 TRUE에 포함됩니다.</p>
</li>
</ul>
<p>-❗️MySQL의 경우 &quot;10 AND 1&quot;과 같이 큰 숫자를 앞에 쓰면 FALSE가 됩니다.
<img src="https://images.velog.io/images/max-sum/post/1b929fdb-8912-4af2-9d9e-e85277e62a33/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.41.08.png" alt=""></p>
<br/>

<p>🌈 <strong>SELECT</strong> &#39;boanana&#39; <strong>NOT BETWEEN</strong> &#39;apple&#39; <strong>AND</strong> &#39;Cola&#39;;</p>
<ul>
<li><p>알파벳도 BETWEEN 연산자를 사용할 수 있으며 MySQL은 대소문자 구분이 없습니다.</p>
</li>
<li><p>NOT을 넣으면 반대의 의미를 갖습니다.
<img src="https://images.velog.io/images/max-sum/post/b8b4d0c4-fc67-47c6-956f-d6de60d09155/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.45.47.png" alt=""></p>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> * <strong>FROM</strong> OrderDetails <strong>WHERE</strong> Quantity <strong>BETWEEN</strong> 1 <strong>AND</strong> 10;</p>
<ul>
<li>Quantity가 1에서 10 사이에 있으면 TRUE가 되어 선택됩니다.
<img src="https://images.velog.io/images/max-sum/post/40a493a4-6135-401e-b3b8-fada176bf4e3/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.50.32.png" alt=""></li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong>  1 + 2 <strong>IN (1, 2, 3)</strong>, &#39;holla&#39; <strong>NOT IN (&#39;cola&#39;, &#39;holla&#39;)</strong>;</p>
<ul>
<li><p>IN (...) : 왼쪽 값이 괄호 안 값에 있으면 TRUE</p>
</li>
<li><p>NOT IN (...) : 왼쪽 값이 괄호 안 값에 없으면 TRUE</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/max-sum/post/072715fc-3100-4971-a3ae-da64ac8b6fc0/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.01.04.png" alt=""></p>
<br/>

<p>🌈 <strong>SELECT</strong> * <strong>FROM</strong> Customers <strong>WHERE</strong> Country <strong>IN (&#39;Mexico&#39;, &#39;UK&#39;)</strong>;</p>
<ul>
<li>Country column에서 값이 Mexico와 UK인 경우만 TRUE가 됩니다.
<img src="https://images.velog.io/images/max-sum/post/b98d5ffb-ab1f-4090-aec4-3b9d4ce47732/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.05.13.png" alt=""></li>
</ul>
<br/>

<h3 id="▶︎-패턴-연산자-like">▶︎ 패턴 연산자 LIKE</h3>
<p>🌈 <strong>SELECT</strong> &#39;holla&#39; <strong>LIKE</strong> &#39;HOLLA&#39;, &#39;holla&#39; <strong>LIKE</strong> &#39;H%&#39;, &#39;holla&#39; <strong>LIKE</strong> &#39;h%a&#39;, &#39;hoLLa&#39; <strong>LIKE</strong> &#39;%ll%&#39;;</p>
<ul>
<li><p>LIKE &#39;...%...&#39; : 0~N개의 문자를 가진 패턴</p>
</li>
<li><p>h%의 경우 h 뒤로 0~N개의 문자가 올 수 있다는 의미입니다.</p>
</li>
<li><p>만약 &#39;holla&#39; LIKE &#39;%h&#39;의 경우 h 뒤에 아무것도 오지 않으므로 FALSE가 됩니다.
<img src="https://images.velog.io/images/max-sum/post/7b84ec1d-3308-41a2-a4c2-bcab016653f3/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.21.16.png" alt=""></p>
</li>
<li><p>MySQL은 언제나 대소문자를 가리지 않습니다.</p>
</li>
</ul>
<br/>

<p>🌈 <strong>SELECT</strong> * <strong>FROM</strong> Customers <strong>WHERE</strong> CustomerName <strong>LIKE</strong> &#39;a%&#39;;</p>
<ul>
<li><p>CustomerName column에서 a로 시작하는 데이터가 TRUE가 되어 가져옵니다.</p>
</li>
<li><p>&#39;%a&#39;였다면 a로 끝나는 데이터만 가져옵니다.</p>
</li>
<li><p>%의 위치가 포인트인 연산자입니다.</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/max-sum/post/fa9ac114-ff7b-4991-9857-3e8a52e5cecc/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.27.58.png" alt=""></p>
<br/>

<p>🌈 <strong>SELECT</strong> * <strong>FROM</strong> Employees <strong>WHERE</strong> Notes <strong>LIKE</strong> &#39;%member%&#39;;</p>
<ul>
<li><p>LIKE + % 연산자는 긴 문자열 데이터에서 특정 문자를 포함하는 데이터를 찾을 때 유용합니다.</p>
</li>
<li><p>조건이 &#39;member%&#39;였다면 member로 시작하는 글만 검색됩니다.</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/max-sum/post/a103a6f8-1750-478c-b1bb-a3276f3328dc/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.43.46.png" alt=""></p>
<br/>

<p>🌈 <strong>SELECT</strong> &#39;holla&#39; <strong>LIKE</strong> &#39;_<em>\</em>_<em>&#39;, &#39;holla&#39; <strong>LIKE</strong> &#39;holl</em>&#39;, &#39;holla&#39; <strong>LIKE</strong> &#39;hol_<em>&#39;, &#39;holla&#39; <strong>LIKE</strong> &#39;ho_<strong>&#39;, &#39;hoLLa&#39; __LIKE</strong> &#39;_oll</em>&#39;;</p>
<ul>
<li><p>LIKE &#39;..._...&#39; : _(under bar)갯수만큼 문자를 가진 패턴</p>
</li>
<li><p>언더바 5개를 쓰면 5글자인 경우 TRUE가 됩니다.</p>
</li>
<li><p>언더바 갯수가 포인트인 연산자입니다.</p>
</li>
</ul>
<p><img src="https://images.velog.io/images/max-sum/post/991fdcd7-1429-40aa-a35c-d14f259b0c95/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.35.47.png" alt=""></p>
<br/>

<p>🌈 <strong>SELECT</strong>  * <strong>FROM</strong> Orders <strong>WHERE</strong> CustomerID <strong>LIKE</strong> &#39;_3&#39;;</p>
<ul>
<li>CustomerID가 3으로 끝나고 숫자가 2자리인 경우만 TRUE가 됩니다.
<img src="https://images.velog.io/images/max-sum/post/6cd61c32-483b-483b-9f11-b8487daac7aa/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-28%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.51.07.png" alt=""></li>
</ul>
<br/>

<br/>

<br/>

<p>💕 <strong>참고</strong>: 얄코님 유튜브 강의, SQL 첫걸음</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JS | zsh: command not found: npm에 대한 간단 체크]]></title>
            <link>https://velog.io/@max-sum/JS-zsh-command-not-found-npm</link>
            <guid>https://velog.io/@max-sum/JS-zsh-command-not-found-npm</guid>
            <pubDate>Tue, 14 Dec 2021 09:00:32 GMT</pubDate>
            <description><![CDATA[<p>❗️ 혹시나 <code>zsh: command not found: npm</code>메시지를 보시고
node를 재설치하시기 전이나 설치 후에도 왠지 안되시는 분들께 이 글을 받칩니다.</p>
<p>결론부터 말씀드리자면 저의 경우 node를 설치 / 재설치하면서 zshrc파일을
수정했으나 <strong>저 메시지가 뜨는 터미널</strong>에서 적용을 해주지 않아서 그렇습니다.</p>
<p>재설치는 번거롭고 시간소요가 발생하는데 또 비슷한 일이 생길 때마다 재설치를
하는건 더더욱 낭비고 스트레스니 일단 아래 방법을 먼저 적용해보시기 바랍니다.</p>
<br/>


<p><img src="https://images.velog.io/images/max-sum/post/18b221d6-a75b-48fb-92a7-16aa85a38f47/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.28.55.png" alt=""></p>
<p>저 메시지를 마주하였을 때 평소와 마찬가지로 검색을 하였습니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/425f5e32-54a5-436b-b203-175dcd2e3728/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.32.15.png" alt=""></p>
<p>역시나 여러 해법과 고난의 동료들이 많았습니다.</p>
<p>몇개의 글을 읽어보는데 일단 node 재설치를 권유하는 글들이었습니다.</p>
<br/>

<p>재설치는 은근히 번거롭고 시간이 소비되기 때문에 조금 생각을 해 보았습니다.</p>
<p>음.. 일단 분명히 어제는 됐었는데.. 하며 어제의 설치과정을 돌이켜보다가
문득 명령어 하나가 생각났습니다.</p>
<p>아..!!! <code>source ~/.zshrc</code>...!</p>
<p>node를 설치하기 전부터 켜 놓았던 터미널에서 zshrc 파일 수정에 대해
갱신하지 않아 발생한 일이었습니다.</p>
<br/>

<p><img src="https://images.velog.io/images/max-sum/post/abaadb31-920f-4dde-9275-20e6cb425c0c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.52.32.png" alt=""></p>
<p>저는 위와 같이 한개의 창에 최소 2개 이상의 터미널을 열고 닫으며 사용하는데
오른쪽에만 수정한 내용을 갱신하였고 왼쪽 창에서는 갱신하지 않았던 것입니다.</p>
<br/>

<p><img src="https://images.velog.io/images/max-sum/post/af8e041b-09c7-4945-a003-a1747f18fe1a/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.56.06.png" alt=""></p>
<p>그래서 명령어를 적용하니 바로 아래와 같이 실행 성공!🙂</p>
<p>부디 이 글을 통해 재설치하지 않고 시간을 버시는 분들이 계시기를 바랍니다!^^</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[NestJS | Configuration 설정(+ JWT error 해결)]]></title>
            <link>https://velog.io/@max-sum/NestJS-Environment-variables</link>
            <guid>https://velog.io/@max-sum/NestJS-Environment-variables</guid>
            <pubDate>Fri, 10 Dec 2021 15:29:23 GMT</pubDate>
            <description><![CDATA[<h2 id="글-작성-계기">&gt; 글 작성 계기</h2>
<p>지난번 dotenv를 이용해 환경변수를 세팅하다가 JWT를 만나 좌충우돌한 경험이 있습니다.(🥕 해결 방법 <a href="https://velog.io/@max-sum/NestJS-JWT-.env-401">링크</a>)</p>
<p>그래서 다른 방법의 환경변수 설정에 목말라 있었는데 역시나 순탄치 않았기에
다시 한 번 글을 작성해보려 합니다.</p>
<hr>
<br/>
<br/>

<h2 id="config-모듈로-환경변수-세팅">&gt; config 모듈로 환경변수 세팅</h2>
<h3 id="▶︎-모듈-설치">▶︎ 모듈 설치</h3>
<p>터미널에서 <code>npm i config</code>를 통해 모듈을 인스톨해줍니다.</p>
<p>윈도우 환경에서는 <code>npm i -g win-node-env</code>도 추가로 설치하셔야 합니다.</p>
<br/>
<br/>

<h3 id="▶︎-환경변수-내용-작성">▶︎ 환경변수 내용 작성</h3>
<p>Project 폴더의 루트 경로에 config라는 이름의 폴더를 만든 후 그 안에
각각 <code>default.yml</code>, <code>development.yml</code>, <code>production.yml</code>파일을 만들어 줍니다.</p>
<p>JSON 형식의 파일로 만들어도 상관 없으나 저는 YAML 형식을 사용하였습니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/9ad93b15-c4bc-4a40-a618-8e7439baebae/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-11%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.39.54.png" alt=""></p>
<p>그리고 각각 용도에 맞추어 내용을 삽입해 줍니다.</p>
<p>띄어쓰기는 Tab을 한 번 입력하시면 됩니다.</p>
<br/>

<p><strong>default.yml</strong>: 기본 설정으로 개발환경과 운영환경 모두에 적용됩니다.</p>
<pre><code class="language-yaml">server:
  port: 3000

db:
  type: &#39;postgres&#39;
  port: 5432
  database: &#39;Project_name&#39;

jwt:
  expiresIn: 3600</code></pre>
<br/>

<p><strong>development.yml</strong>: 개발환경에서 필요한 내용(default도 자동으로 적용됨)</p>
<pre><code class="language-yaml">db:
  host: &#39;localhost&#39;
  username: &#39;postgres&#39;
  password: &#39;123abc&#39;
  synchronize: true

jwt:
  secret: &#39;mysecret123key&#39;</code></pre>
<br/>

<p><strong>production.yml</strong>: 운영환경에서 필요한 내용(default도 자동으로 적용됨)</p>
<pre><code class="language-yaml">db:
  synchronize: false</code></pre>
<br/>

<h3 id="▶︎-환경변수-적용">▶︎ 환경변수 적용</h3>
<p>아래는 Database에 환경변수를 적용한 예시입니다.</p>
<pre><code class="language-js">import * as config from &#39;config&#39;;
import { TypeOrmModuleOptions } from &quot;@nestjs/typeorm&quot;;

const dbConfig = config.get(&#39;db&#39;)

export const typeORMConfig: TypeOrmModuleOptions = {
    type: dbConfig.type,
    host: process.env.RDS_HOST || dbConfig.host,
    port: process.env.RDS_PORT || dbConfig.port,
    username: process.env.RDS_USERNAME || dbConfig.username,
    password: process.env.RDS_PASSWORD || dbConfig.password,
    database: process.env.RDS_DATABASE || dbConfig.database,
    entities: [__dirname + &#39;/../**/*.entity.{js, ts}&#39;],
    synchronize: dbConfig.synchronize
}</code></pre>
<p><code>import * as config from &#39;config&#39;;</code>로 모듈을 가져오고
<code>config.get(&#39;환경변수_이름&#39;)</code>으로 우선 큰 단위의 환경변수 이름을 지정하여 
변수에 담아 놓습니다.</p>
<p>해당 환경변수 하위 항목의 이름을 Dot notation으로 호출합니다.(🥕 <a href="https://docs.nestjs.kr/techniques/configuration#expandable-variables">공식문서 보기</a>)</p>
<p><code>process.env.RDS_HOST</code>같은 부분은 RDS에 연결했을 때 그에 맞게 만들어놓은
환경변수를 사용하고, 없으면 config 모듈을 통해 설정해 놓은 환경변수를 사용하도록
<code>||</code>연산자를 이용해 지정한 것으로 이 부분은 헷갈리시면 우선 지우셔도 됩니다.</p>
<p>뭐.. 여기 까지는 순탄했습니다만 이번에도 JWT secret이 난리였습니다.</p>
<br/>


<h3 id="▶︎-jwt-secret-typeerror와-해결">▶︎ JWT secret TypeError와 해결</h3>
<pre><code class="language-js">const jwtConfig = config.get(&#39;jwt&#39;)

@Module({
  imports: [
    JwtModule.register({
      secret: process.env.JWT_SECRET || jwtConfig.secret,
      signOptions: { expiresIn: jwtConfig.expiresIn }
    }),
    PassportModule.register({ defaultStrategy: &#39;jwt&#39; }),
    TypeOrmModule.forFeature([UserRepository]),
  ],
  ...</code></pre>
<p>이 방법이 정석이지만 저의 경우 저대로 작성해 놓으면 jwt secret 부분이 계속해서 
TypeError가 발생하였습니다.</p>
<p>jwt strategy의 <code>secretOrKey</code> 부분도 마찬가지였습니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/ac4a1aa6-05cb-4328-8689-5089f9612c6f/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-11%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.00.25.png" alt=""></p>
<p>이런 경우 다음과 같이 해당 변수 부분을 <code>`${}`</code>으로 감싸주시면 해결됩니다.</p>
<p><code>secret: `${jwtConfig.secret}`</code></p>
<p>호호..</p>
<br/>

<p>dotenv때부터 저를 괴롭히던 부분이었고 지난번에 뭔가 보기도 안좋고 찝찝한 
느낌으로 마무리 되었는데 되돌아보니 그래도 나름 다 잘 해결해나간 것 같아
기분이 좋습니다.😃</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[NestJS | JWT와 dotenv 401 해결]]></title>
            <link>https://velog.io/@max-sum/NestJS-JWT-.env-401</link>
            <guid>https://velog.io/@max-sum/NestJS-JWT-.env-401</guid>
            <pubDate>Wed, 08 Dec 2021 16:22:21 GMT</pubDate>
            <description><![CDATA[<h2 id="이전-상태">&gt; 이전 상태</h2>
<p>NestJS에서 JWT 모듈을 등록하던 중 secret key를 .env파일을 통해 적용하려 했었는데
계속해서 <code>&quot;statusCode&quot;: 500</code>이 발생하였던 적이 있습니다.</p>
<p>그래서 검색을 통해 해결책을 알아냈었고 다음과 같이 .env를 호출할 때 앞에
<code>&quot;&quot;+</code>를 붙여 성공하였었습니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/f55a83c6-debd-4aff-b1f7-f232d4182de9/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-08%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.44.04.png" alt=""></p>
<p>뭔가 마음에 들지 않았지만 학습의 흐름이 끊기지 않는 것이 우선이라 생각해서
어느정도 진도를 나간 후 확인해보기 위해 우선 그대로 두었습니다.</p>
<p>그리고 곧...🥲</p>
<br/>

<h2 id="오류-내용">&gt; 오류 내용</h2>
<p>그리고 <code>@UseGuards(AuthGuard())</code>를 통해 유저 정보를 가져오기 위해서
테스트를 시행해 보았는데 계속해서 <code>&quot;statusCode&quot;: 401</code>만 출력되었습니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/2b39a056-4503-4230-b75b-77f105ffaa5e/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-08%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.57.21.png" alt=""></p>
<p>검색 결과 위와 같은 글을 찾았고 즉시 key를 넣는 부분에 .env를 호출하는 대신
<code>&#39;123&#39;</code>으로 JwtModule과 JwtStrategy의 키를 모두 바꾸고 실행해 보았습니다.</p>
<p>그리고 더이상 401이 발생하지 않고 유저 정보를 잘 가져올 수 있었습니다.</p>
<p>하지만 이렇게 마무리하면 의미가 없다 생각했습니다.</p>
<p>.env를 제대로 사용할 수 없으니까요.</p>
<br/>

<h2 id="해결-과정-및-방법">&gt; 해결 과정 및 방법</h2>
<blockquote>
<p>❗️2011.12.11일 추가:<br>이후 <a href="https://docs.nestjs.kr/techniques/configuration#custom-configuration-files">yalm 파일을 통한 custom 환경설정</a>을 통해 .env를 사용하지 않고 환경변수를 설정하였습니다.
다른 환경변수 설정 방법이 궁금하신 분은 <a href="https://velog.io/@max-sum/NestJS-Environment-variables">🥕 링크</a>를 눌러주세요!</p>
</blockquote>
<p>일단 환경변수가 제대로 리턴되는지 확인하는 방법을 찾게되어 터미널에 <code>node</code>를 
입력한 후 환경변수 동작이 잘 되는지 확인해 보았습니다.</p>
<p><img src="https://images.velog.io/images/max-sum/post/5fe0b3d2-447d-4d87-9e44-0767fca60c9d/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-08%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2011.16.17.png" alt=""></p>
<p>아... 왜...?? </p>
<p><img src="https://images.velog.io/images/max-sum/post/5b06d5b9-3ef4-4792-ae90-58ed89aea555/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-09%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.04.42.png" alt=""></p>
<p>그런데 또 <code>console.log(process.env)</code>를 통해서는 출력이 되는..왜..????</p>
<br/>

<p>우선 호출이 되므로 후다닥 우당탕탕 쨍그랑 이것저것 한시간정도 적용해보다 
결국 다음 한 줄을 넣어 성공했습니다.</p>
<p><code>require(&quot;dotenv&quot;).config();</code></p>
<p><img src="https://images.velog.io/images/max-sum/post/1fdf8c6b-97e8-4e5f-8792-1252ca3d6a28/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-09%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.10.31.png" alt=""></p>
<p><img src="https://images.velog.io/images/max-sum/post/36495329-73fd-40e0-b415-c22ee6515b9f/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-09%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.16.06.png" alt=""></p>
<p>아마도 사용하는 모듈에 .env가 제대로 적용 되고있지 않았던 것 같습니다.</p>
<p>공식문서대로라면 이렇게 하지 않아도 동작했기 때문에 차후 같은 일이 반복되면
지금의 경험을 바탕으로 더 깊이 알아봐야겠습니다.</p>
<p>오늘도 성취감을 얻고 약간의 시력을 잃은 것 같습니다.😎</p>
<p>혹시나 이 글을 보시는 분께서도 잘 해결되셨길 바라며 글을 마치겠습니다!^^</p>
<hr>
<br/>
<br/>
<br/>

<h3 id="▶︎-🌈-작은-회고-🤔">▶︎ 🌈 작은 회고 🤔</h3>
<p>참 오랜만에 블로그 글을 쓰는 것 같습니다.</p>
<p>wecode 부트캠프를 수료하고 이제 취업준비를 시켜주시는데 여간 빡쎈게 아닙니다.</p>
<p>주니어 개발자의 이력서가 세상 이력서 중 가장 작성하기 어렵지 않나 싶습니다.</p>
<p>동시에 면접준비와 기초 소양을 위해 또 많은 것을 공부해야하고</p>
<p>저같은 경우 Django에서 NestJS로 전향하기 위해 조금 더 신경써야할 부분도 있습니다.</p>
<br/>

<p>아무튼 이런 저런 압박감들 속에서 다행히 같이 취업준비를 하기 위해 모인 분들의 </p>
<p>성품이 너무나 좋으시고 도움도 많이 주셔서 힘든 와중에 큰 힘이 되고 있습니다.</p>
<br/>

<p>이렇게 글로 남기지 않으면 훗날 지금의 고난과 감사함을 잊고 겸손함도 잊게 될까봐</p>
<p>작성 완료를 누른 후에 다시 수정하러 오게 되었습니다.</p>
<p>개인적으로 여러가지 악조건에 있지만 오늘 해결한 문제처럼 모두 뚫고 전진해서</p>
<p>훗날 개발자 세상에 뛰어들어 고난을 헤치며 지쳐있는 분들에게 힘이 되었으면 합니다.</p>
<p>이러한 마음으로 오늘도 작은 기록을 남겨봅니다.🙂</p>
]]></description>
        </item>
    </channel>
</rss>