Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- islowercase()
- 최대공약수
- 자바 스트링
- toLowerCase()
- 스프링환경설정
- 스프링
- 최소공배수
- 모던자바
- replaceAll()
- addDoc
- string
- 베주계수
- 동일성과 동등성
- isuppercase()
- 스프링뼈대
- 유클리드호제법
- git 컨벤션
- 최대공약수와 최소공배수
- 래퍼타입
- ineer join
- Git사용법
- while과 two-pointer
- sql 데이터형 변환
- StringBuilder
- string과 stringbuilder
- stringbuilder의 reverse()
- 자바 최소공배수
- 자바 최대공약수
- 자바 유클리드
- 프로그래머스 레벨1
Archives
- Today
- Total
주노 님의 블로그
20240711 사전캠프 9일차 TIL 본문
사전캠프 9일차 내용 간단요약
- 14:00 ~ 14:10 : 어제 TIL 복습
- 14:10 ~ 15:00 : SQL(31~43)
- 15:00 ~ 16:30 : 강의 (엑셀보다 쉽고 빠른 SQL) : 5주차
PIVOT TABLE, WINDOW FUNCTION, DATE형 - 16:30 ~ 17:30 : 웹개발 종합반 복습
- 17:30 ~ 18:00 : TIL정리
강의 (엑셀보다 쉽고 빠른 SQL) : 5주차
더보기
- 조인을 했을때 쓸모없는 값이 있다면?
IF문으로 NULL값을 제거해준다, COALESCE를 사용한다 - 사용 해야하는 이유
평균의 값이 왜이렇게 다른가?
MYSQL에서는 평균등을 매길때 Not given과 같은 이상한 값을 0으로 처리해서 계산을 한다.
즉, 별점을 평균내는데 점수를 매기지 않은 사람들이 있다면 자동으로 0이 되어버림.
NULL로 한다면 평균을 내지않음, 따라서 NULL로 바꾸는 과정이 필요함 - IF문을 사용하기
IF(RATING이 NOT GIVEN이 아니라면, RATING값 그대로, NOTGIVEN이라면 NULL로 바꿔준다.select restaurant_name, avg(rating) average_of_rating, avg(if(rating<>'Not given', rating, null)) average_of_rating2 from food_orders group by 1
- NULL 사용하기
IS NULL, IS NOT NULL을 사용한다.
CUSTOMER_ID가 NULL이 아닌 조건만 사용한다.select a.order_id, a.customer_id, a.restaurant_name, a.price, b.name, b.age, b.gender from food_orders a left join customers b on a.customer_id=b.customer_id where b.customer_id is not null
- 조인을 했는데 정상적이지 않은 값이 있다면?
조건문으로 값의 범위를 정해준다. - PIVOT TABLE
PIVOT TABLE이란? 여러 데이터를 요약하고 집계할때 보기 쉽게 배열하여 보여주는것.
~별 ~별 주문건수 이럴때 잘 쓰인다.
위 코드에서 내부쿼리는select restaurant_name, max(if(hh='15', cnt_order, 0)) "15", max(if(hh='16', cnt_order, 0)) "16", max(if(hh='17', cnt_order, 0)) "17", max(if(hh='18', cnt_order, 0)) "18", max(if(hh='19', cnt_order, 0)) "19", max(if(hh='20', cnt_order, 0)) "20" from ( select a.restaurant_name, substring(b.time, 1, 2) hh, count(1) cnt_order from food_orders a inner join payments b on a.order_id=b.order_id where substring(b.time, 1, 2) between 15 and 20 group by 1, 2 ) a group by 1 order by 7 desc
각 레스토랑별 시간대별 주문 건수를 세는것을 볼 수 있다.
외부 쿼리에서는
내부쿼리에서 계산한 레스토랑별 시간대별 주문건수를 가져다쓰는데, 각 시간에 값이 있다면 CNT_ORDER값을 가져오고 없을시 0을 반환하는것을 볼 수 있다.
왜 MAX를 썼을까?
만에하나 그룹화된 결과에서 중복된 컬럼이 있을 경우를 대비한 것이다.
즉 PIVOT TABLE을 만들기 위해서는 SELECT문 최 상단에 열을, 그다음 행만큼의 조건을 써내려가면된다..
위의 문제의 경우에는 SELECT 퀴진타입, 10대조건, 20대조건, 30대조건, 40대조건, 50대조건. 6개가 들어가게된다.
완성된 코드는 위와 같다.SELECT CUISINE_TYPE, MAX(IF(AGE_GROUP = 10, ORDER_CNT, 0)) AS "10대", MAX(IF(AGE_GROUP = 20, ORDER_CNT, 0)) AS "20대", MAX(IF(AGE_GROUP = 30, ORDER_CNT, 0)) AS "30대", MAX(IF(AGE_GROUP = 40, ORDER_CNT, 0)) AS "40대", MAX(IF(AGE_GROUP = 50, ORDER_CNT, 0)) AS "50대" FROM ( SELECT fo.CUISINE_TYPE, CASE WHEN cu.AGE >= 10 AND cu.AGE < 20 THEN 10 WHEN cu.AGE >= 20 AND cu.AGE < 30 THEN 20 WHEN cu.AGE >= 30 AND cu.AGE < 40 THEN 30 WHEN cu.AGE >= 40 AND cu.AGE < 50 THEN 40 WHEN cu.AGE >= 50 AND cu.AGE < 60 THEN 50 END AS AGE_GROUP, COUNT(1) AS ORDER_CNT FROM food_orders fo INNER JOIN customers cu ON cu.customer_id = fo.customer_id WHERE cu.AGE BETWEEN 10 AND 59 GROUP BY fo.CUISINE_TYPE, AGE_GROUP ) AS A GROUP BY CUISINE_TYPE ORDER BY CUISINE_TYPE;
두개의 테이블의 값을 불러오기 위해 조인을 하였다.SELECT fo.CUISINE_TYPE, cu.AGE FROM food_orders fo INNER JOIN customers cu ON cu.customer_id = fo.customer_id
SELECT fo.CUISINE_TYPE, CASE WHEN cu.AGE >= 10 AND cu.AGE < 20 THEN 10 WHEN cu.AGE >= 20 AND cu.AGE < 30 THEN 20 WHEN cu.AGE >= 30 AND cu.AGE < 40 THEN 30 WHEN cu.AGE >= 40 AND cu.AGE < 50 THEN 40 WHEN cu.AGE >= 50 AND cu.AGE < 60 THEN 50 END AS AGE_GROUP FROM food_orders fo INNER JOIN customers cu ON cu.customer_id = fo.customer_id
연령대를 그룹화 하기 위해 CASE WHEN절을 사용하였다.
음식종류별, 연령대별 주문건수를 세기 위해 COUNT절을 달아주고, GROUP BY를 사용하였다.SELECT fo.CUISINE_TYPE, CASE WHEN cu.AGE >= 10 AND cu.AGE < 20 THEN 10 WHEN cu.AGE >= 20 AND cu.AGE < 30 THEN 20 WHEN cu.AGE >= 30 AND cu.AGE < 40 THEN 30 WHEN cu.AGE >= 40 AND cu.AGE < 50 THEN 40 WHEN cu.AGE >= 50 AND cu.AGE < 60 THEN 50 END AS AGE_GROUP, COUNT(1) AS ORDER_CNT FROM food_orders fo INNER JOIN customers cu ON cu.customer_id = fo.customer_id WHERE cu.AGE BETWEEN 10 AND 59 GROUP BY fo.CUISINE_TYPE, AGE_GROUP
또한 나이 10~59세만 가져오기 위하여 WHERE절을 추가하였다.
외부쿼리는 피벗을 만들기위해 SELECT절, 음식 종류를 묶기위해 GROUP BY절을 사용하였다 - WINDOW FUNCTION이란?
원래의 행 데이터를 보존하면서도, 추가적인 계산을 할 수 있게 하는것.
SUM이나, AVG함수라면 결과값이 그룹화된 하나의 값으로 나타나겠지만
WINDOW FUNCTION은 그대로 유지해준다.
위와같은 EMPLOYEES 테이블이 있다고 가정해보자
집계함수 SUM을 사용해서 나타낸다면SELECT department_id, SUM(salary) AS total_salary FROM employees GROUP BY department_id;
쿼리의 결과는 위와같이 될것이다.
윈도우함수 SUM() OVER ~을 사용하였다면SELECT employee_id, department_id, salary, SUM(salary) OVER (PARTITION BY department_id) AS total_salary FROM employees;
쿼리의 결과는 이전과 동일하되, TOTAL_SALARY란만 늘어난것을 볼 수 있다.
사용법
window_function(argument) over (partition by 그룹 기준 컬럼 order by 정렬 기준)
window_function : 사용할 함수 ROW_NUMBER(), RANK(), SUM(), AVG(), COUNT()
argument : 함수가 적용될 열, ROW_NUMBER(), RANK()는 없어도 되지만, SUM이나 AVG, COUNT는 들어가야한다.
OVER : WINDOW함수를 쓰기위한 필수 키워드
PARTITION BY : 데이터를 나누는 기준, 결과값을 나타낼때 그룹하는 기준.
ORDER BY : 데이터를 정렬하는 기준.
위 SUM ~ OVER절을 분석해보자
윈도우 함수로 SUM을 사용했으며, 함수가 적용될 열(계산할 열)은 SALARY이다.
department_id기준으로 데이터를 나누었다.
ROW_NUMBER() - 각 파티션 별로 고유한 순위 번호를 나타낼 때
RANK() - 각 파티션 내 순위를 매기지만, 동일한 값을 가지면 동일한 순위를 부여, 다음번호는 건너뛴다. - DATE형
데이터에 날짜를 지정할때나, DATE형을 문자형으로 변환할때 사용 - DATE_FORMAT
DATE형을 본인이 원한 포맷으로 바꾸는데 사용된다.
DATE_FORMAT(DATE(DATE), '%Y') "년", DATE_FORMAT(DATE(DATE), '%m') "년", DATE_FORMAT(DATE(DATE), '%Y%m') "년월",
'TIL' 카테고리의 다른 글
20240715 본캠프 1일차 TIL (0) | 2024.07.15 |
---|---|
20240712 사전캠프 10일차 TIL (0) | 2024.07.12 |
20240710 사전캠프 8일차 TIL (0) | 2024.07.10 |
20240709 사전캠프 7일차 TIL (0) | 2024.07.09 |
20240708 사전캠프 6일차 TIL (0) | 2024.07.08 |