Write a query identifying the type of each record in the TRIANGLES table using its three side lengths. Output one of the following statements for each record in the table:
Isosceles
Equilateral
Scalene
Not A Triangle
(20, 20, 23): Isosceles triangle, A≡B.
(20, 20, 20): Equilateral triangle, A≡B≡C.
(20, 21, 22): Scalene triangle, A≠B≠C.
(13, 14, 30): cannot triangle, A and B is not larger than that of side C.
CASE
WHEN 조건식1THEN 식1
[WHEN 조건식2 THEN 식2...]
[ELSE 식3]
END
또는
CASE 식1
WHEN 식2 THEN 식3
[WHEN 식4 THEN 식5...]
[ELSE 식6]
END
SELECT
CASE WHEN A + B > C AND A + C > B AND B + C > A THEN CASE
WHEN A = B AND B = C THEN 'Equilateral'
WHEN A = B OR A = C OR B = C THEN 'Isosceles'
ELSE 'Scalene'
ELSE 'Not A Triangle'
FROM TRIANGLES;
SELECT
CASE
WHEN A + B > C AND B + C > A AND C + A > B THEN
CASE
WHEN A = B AND B = C THEN 'Equilateral'
WHEN A = B OR A = C OR B = C THEN 'Isosceles'
ELSE 'Scalene'
END
ELSE 'Not A Triangle'
END
FROM TRIANGLES;
CASE-WHEN
함수를 파이썬의 if-else
문으로 먼저 작성해본 뒤 쿼리문을 작성했다.if a + b > c and a + c > b and b + c > a: # 삼각형이라면,
if a == b == c: # 세 변의 길이가 같다면,
result = "Equilateral"
else:
if a == b or a == c or b == c: # 두 변의 길이가 같다면,
result = "Isosceles"
else: # 모든 변의 길이가 같지 않다면,
result = "Scalene"
else: # 삼각형이 아니라면,
result = "Not A Triangle"
SELECT
CASE
WHEN A + B > C AND A + C > B AND B + C > A THEN
CASE
WHEN A = B AND B = C THEN 'Equilateral'
ELSE
CASE
WHEN A = B OR A = C OR B = C THEN 'Isosceles'
ELSE 'Scalene'
END
END
ELSE 'Not A Triangle'
END
FROM TRIANGLES;
CASE-WHEN
에서 elif는 없지만 그냥 이어서 WHEN
을 쓰면 되는건데, 그걸 간과하고 바로 ELSE
로 넘겨서 다른 조건절을 만든것이었다.# 1. 삼각형이냐?
if a + b > c and a + c > b and b + c > a: # 삼각형이라면,
# 2. 변의 길이가 몇개나 같냐?
if a == b == c: # 세 변의 길이가 같다면,
result = "Equilateral"
elif a == b or a == c or b == c: # 두 변의 길이가 같다면,
result = "Isosceles"
else: # 모든 변의 길이가 같지 않다면,
result = "Scalene"
else: # 삼각형이 아니라면,
result = "Not A Triangle"
CASE
안의 CAS
E로, 즉 총 두개의 CASE
로 줄였다.SELECT
CASE
WHEN A + B > C AND A + C > B AND B + C > A THEN
CASE
WHEN A = B AND B = C THEN 'Equilateral'
WHEN A = B OR A = C OR B = C THEN 'Isosceles'
ELSE 'Scalene'
END
ELSE 'Not A Triangle'
END
FROM TRIANGLES;
if a + b <= c or a + c <= b or b + c > a: # 삼각형이 아니냐?
result = "Not A Triangle"
elif a == b == c: # 세 변의 길이가 같냐?
result = "Equilateral"
elif a == b or a == c or b == c: # 두 변의 길이가 같냐?
result = "Isosceles"
else: # 모두다 아닌, 즉 모든 변의 길이가 같지 않다면,
result = "Scalene"
SELECT
CASE
WHEN A + B <= C OR A + C <= B OR B + C <= A THEN 'Not A Triangle'
WHEN A = B AND B = C THEN 'Equilateral'
WHEN A = B OR A = C OR B = C THEN 'Isosceles'
ELSE 'Scalene'
END
FROM TRIANGLES;
CASE-WHEN
을 else if가 없다고 착각했기 때문이다. 순서대로 조건을 탐색하니까, 바로 이어서 WHEN
을 작성하면 되는데..Generate the following two result sets:
1. Query an alphabetically ordered list of all names in OCCUPATIONS, immediately followed by the first letter of each profession as a parenthetical (i.e.: enclosed in parentheses).
For example:AnActorName(A), ADoctorName(D), AProfessorName(P), and ASingerName(S)
.
2. Query the number of ocurrences of each occupation in OCCUPATIONS. Sort the occurrences in ascending order, and output them in the following format:There are a total of [occupation_count] [occupation]s.
where[occupation_count]
is the number of occurrences of an occupation in OCCUPATIONS and[occupation]
is the lowercase occupation name. If more than one Occupation has the same[occupation_count]
, they should be ordered alphabetically.
Note: There will be at least two entries in the table for each type of occupation.
Occupation will only contain one of the following values: Doctor, Professor, Singer or Actor.
Ashely(P)
Christeen(P)
Jane(A)
Jenny(D)
Julia(A)
Ketty(P)
Maria(A)
Meera(S)
Priya(S)
Samantha(D)
There are a total of 2 doctors.
There are a total of 2 singers.
There are a total of 3 actors.
There are a total of 3 professors.
first query: formatted to the problem description's specifications.
second query: ascendingly ordered first by number of names corresponding to each profession (2≤2≤3≤3), and then alphabetically by profession (doctor≤singer, and actor≤professor).
LEFT(string-expression, integer)
CONCAT
||
+
LOWER('문자열')
: 대문자를 소문자로 바꿈SELECT CONCAT(Name, '(', LEFT(Occupation, 1), ')')
FROM OCCUPATIONS
ORDER BY Name;
SELECT CONCAT('There are a total of ', COUNT(Occupation), ' ', LOWER(Occupation), 's')
FROM OCCUPATIONS
ORDER BY COUNT(Occupation), Occupation;
ERROR 1140 (42000) at line 4: In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'OCCUPATIONS.Occupation'; this is incompatible with sql_mode=only_full_group_by
GROUP BY
를 잊지 말자!SELECT CONCAT(Name, '(', LEFT(Occupation, 1), ')')
FROM OCCUPATIONS
ORDER BY Name;
SELECT CONCAT('There are a total of ', COUNT(Occupation), ' ', LOWER(Occupation), 's.')
FROM OCCUPATIONS
GROUP BY Occupation
ORDER BY COUNT(Occupation), Occupation;
+
를 써서 문자열을 연결한다면, COUNT(Occupation)
는 숫자이므로 오류가 발생한다!Pivot the Occupation column in OCCUPATIONS so that each Name is sorted alphabetically and displayed underneath its corresponding Occupation. The output column headers should be Doctor, Professor, Singer, and Actor, respectively.
Note: Print NULL when there are no more names corresponding to an occupation.
Occupation will only contain one of the following values: Doctor, Professor, Singer or Actor.
Jenny Ashley Meera Jane
Samantha Christeen Priya Julia
NULL Ketty NULL Maria
The first column is an alphabetically ordered list of Doctor names.
The second column is an alphabetically ordered list of Professor names.
The third column is an alphabetically ordered list of Singer names.
The fourth column is an alphabetically ordered list of Actor names.
The empty cell data for columns with less than the maximum number of names per occupation (in this case, the Professor and Actor columns) are filled with NULL values.
ROW_NUMBER() OVER (PARTITION BY Occupation ORDER BY Name)
: 직업(Occupation) 별로 이름(Name) 순서에 따라 고유한 순위를 부여한다.
SELECT Occupation
, Name
, ROW_NUMBER() OVER (PARTITION BY Occupation ORDER BY Name) AS rn
FROM OCCUPATIONS;
- 각 직업 안에서 순위를 매겨서, 다른 직업에서는 다시 1부터 시작.
CASE WHEN
사용해서 해당 직업일 때 이름 표시하고, 아니라면 결측치(null)로 표시SELECT rn
, Occupation
, Name
, (CASE WHEN Occupation = 'Doctor' THEN Name ELSE NULL END) AS doctor
FROM (
SELECT Occupation
, Name
, ROW_NUMBER() OVER (PARTITION BY Occupation ORDER BY Name) AS rn
FROM OCCUPATIONS
) AS rn_table
WHERE rn = 1;
- rn=1일때, 즉 각 직업에서 첫번째 이름만 뽑고, Doctor일 때만 이름 표시했더니, 다른 직업은 다 null로 나옴.
SELECT rn
, MIN(CASE WHEN Occupation = 'Doctor' THEN Name ELSE NULL END) AS doctor
, MIN(CASE WHEN Occupation = 'Professor' THEN Name ELSE NULL END) AS professor
, MIN(CASE WHEN Occupation = 'Singer' THEN Name ELSE NULL END) AS singer
, MIN(CASE WHEN Occupation = 'Actor' THEN Name ELSE NULL END) AS actor
FROM (
SELECT Occupation
, Name
, ROW_NUMBER() OVER (PARTITION BY Occupation ORDER BY Name) AS rn
FROM OCCUPATIONS
) AS rn_table
WHERE rn = 1
GROUP BY rn;
- 각 직업에서 첫번째 이름이 각 컬럼으로 출력되었다.
SELECT MIN(CASE WHEN Occupation = 'Doctor' THEN Name ELSE NULL END) AS doctor
, MIN(CASE WHEN Occupation = 'Professor' THEN Name ELSE NULL END) AS professor
, MIN(CASE WHEN Occupation = 'Singer' THEN Name ELSE NULL END) AS singer
, MIN(CASE WHEN Occupation = 'Actor' THEN Name ELSE NULL END) AS actor
FROM (
SELECT Occupation
, Name
, ROW_NUMBER() OVER (PARTITION BY Occupation ORDER BY Name) AS rn
FROM OCCUPATIONS
) AS rn_table
GROUP BY rn
ORDER BY rn;
You are given a table, BST, containing two columns: N and P, where N represents the value of a node in Binary Tree, and P is the parent of N.
Write a query to find the node type of Binary Tree ordered by the value of the node. Output one of the following for each node:
1 Leaf
2 Inner
3 Leaf
5 Root
6 Leaf
8 Inner
9 Leaf
The Binary Tree below illustrates the sample:
SELECT DISTINCT BST.N,
CASE
WHEN BST.P is null THEN 'Root'
WHEN child.P is null THEN 'Leaf'
ELSE 'Inner'
END
FROM BST
LEFT JOIN BST AS child ON BST.N = child.P
ORDER BY BST.N;
아래 데이터리안의 JOIN 사용한 풀이와 같은 내용이지만, 아래 설명이 훨씬 쉽다!
데이터리안 해설 보기 전 풀이
: 보다 비효율적인 조건 찾기(즉, Root 부터 찾는게 편한데 Inner 부터 찾는다면)..
-- N P N2 P2 => P -> N -> N2 순서
-- 자식(N2) & 부모(P) 둘다 있으면: Inner
-- 자식(N2)은 있는데 부모(P)는 없으면: Root
-- 자식(N2)은 없고 부모(P)만 있으면: Leaf
SELECT DISTINCT a.N
, CASE
WHEN b.N IS NOT NULL AND a.P IS NOT NULL THEN "Inner"
WHEN b.N IS NOT NULL THEN "Root"
ELSE "Leaf"
END AS node
FROM BST a
LEFT JOIN BST b ON a.N = b.P
ORDER BY a.N;
JOIN 사용
SELECT DISTINCT a.N
, CASE
WHEN a.P IS NULL THEN "Root"
WHEN b.N IS NULL THEN "Leaf"
ELSE "Inner"
END AS node
FROM BST a
LEFT JOIN BST b ON a.N = b.P
ORDER BY a.N;
서브쿼리 사용
SELECT N
, CASE
WHEN P IS NULL THEN "Root"
WHEN N IN (SELECT DISTINCT P FROM BST) THEN "Inner"
ELSE "Leaf"
END
FROM BST
ORDER BY N;
JOIN 사용과 서브쿼리 사용시 조건 탐색의 순서가 다르다.
Amber's conglomerate corporation just acquired some new companies. Each of the companies follows this hierarchy:
Given the table schemas below, write a query to print the company_code, founder name, total number of lead managers, total number of senior managers, total number of managers, and total number of employees. Order your output by ascending company_code.
The following tables contain company data:
Company Table:
Lead_Manager Table:
Senior_Manager Table:
Manager Table:
Employee Table:
C1 Monika 1 2 1 2
C2 Samantha 1 1 2 2
In company C1, the only lead manager is LM1. There are two senior managers, SM1 and SM2, under LM1. There is one manager, M1, under senior manager SM1. There are two employees, E1 and E2, under manager M1.
In company C2, the only lead manager is LM2. There is one senior manager, SM3, under LM2. There are two managers, M2 and M3, under senior manager SM3. There is one employee, E3, under manager M2, and another employee, E4, under manager, M3.
처음 SQL 스터디에서 풀지 못했던 문제를 이번에 다시 풀면서 성공!
우선 정답:
SELECT C.company_code
, C.founder
, COUNT(DISTINCT(L.lead_manager_code))
, COUNT(DISTINCT(S.senior_manager_code))
, COUNT(DISTINCT(M.manager_code))
, COUNT(DISTINCT(E.employee_code))
FROM Company AS C
LEFT JOIN Lead_Manager AS L ON C.company_code = L.company_code
LEFT JOIN Senior_Manager AS S ON L.company_code = S.company_code
LEFT JOIN Manager AS M ON S.company_code = M.company_code
LEFT JOIN Employee AS E ON M.company_code = E.company_code
GROUP BY C.company_code, C.founder
ORDER BY C.company_code;
"어? Employee 에 다 나와있네? 그럼 Company와 Employee 테이블만 join하면 되는거 아냐?"라는 생각에 많이들 실수하는데, 이러면 예외 케이스가 누락된다!!!
LEFT JOIN
을 해야할까?SM2 사례처럼, 상위 직책이 존재해도 하위 직책이 부여된다는 보장이 없다. 설령 리드 매니저 아래 직책이 없다고 해도, 리드 매니저는 output에 표시되어야 한다.
직책은 계층구조로 구성되어 있다. 회사-창업자-리드 매니저-시니어 매니저-매니저-직원
SELECT
에서 어느 테이블의 컬럼인지 명시해야할까?어느 테이블의 컬럼을 의미하는지 정확히 명시하자!(예: L.lead_manager_code)
GROUP BY
에서 C.founder도 정의한걸까?사실 그동안 습관적으로 컬럼명 다음에 바로 콤마를 찍었는데.. 데이터리안 해설 강의를 보면서 매우 잘못된 습관이란걸 깨달았다!
SELECT C.company_code
, C.founder
, (SELECT COUNT(DISTINCT lead_manager_code)
FROM Lead_Manager
WHERE company_code = C.company_code)
, (SELECT COUNT(DISTINCT senior_manager_code)
FROM Senior_Manager
WHERE company_code = C.company_code)
, (SELECT COUNT(DISTINCT manager_code)
FROM Manager
WHERE company_code = C.company_code)
, (SELECT COUNT(DISTINCT employee_code)
FROM Employee
WHERE company_code = C.company_code)
FROM Company AS C
-- GROUP BY C.company_code, C.founder
ORDER BY company_code;
WHERE
로 Company 테이블의 company_code와 맞도록 조건을 건다.