240801

Gi Woon Lee·2024년 8월 1일
0

TIL

목록 보기
29/78

CASE WHEN

CASE WHEN DISTINCT '칼럼' > 5 THEN '출력값'
했다가 계속 오류가 생겨서 찾아보니

DISTINCT 는 CASE절에서 사용할 수 없다.

CASE WHEN 함수는 row by row 함수이며,
DISTINCT 하나의 칼럼 전체에 사용하는 것이 아니라, 특정 범위에서 사용한다.

COUNT()

COUNT는 해당 열의 모든 행을 COUNT하는 역할을 수행한다. 일반적으로 ()안에는 칼럼의 이름이나 "*"이 위치한다.

COUNT 안에 인자값을 넣게 되면, 해당 인자값이 포함된 칼럼의 행 수를 COUNT한다.

따라서 인자값(ex- james)의 개수를 알기 위해서 COUNT('james')를 돌려도 원하는 값을 얻지 못한다.
'james'라는 문자열이 있는 모든 행의 개수를 세기 때문이다.

특정 인자값이 들어있는 경우만은 세고 싶다면 조건절(CASE)을 사용해야 한다.

COUNT() 는 NULL 빼고 전부 센다. 0도 COUNTING 한다.

"RANK" 칼럼에 1,2,3,4,5,0 이 각 행에 있다고 하면,
COUNT(RANK) 는 5가 아니라 6이다!

하지만 칼럼에 1,2,3,4,5,NULL 이 있다면
COUNT(RANK) 는 5가 맞다.

COUNT(CASE WHEN action = 'confirmed' THEN 1 ELSE 0 END) ```

위 경우, count는 1과 0 전부를 counting하기 때문에 결과값이 COUNT(action)과 똑같이 나온다.

즉, case when을 통한 필터링 기능이 작동하지 않는다.

SELECT user_id, COUNT(CASE WHEN action = 'confirmed' THEN 1 END) AS confirmed_count
FROM Confirmations
GROUP BY user_id;

-- user_id 끼리 묶고, action 칼럼의 결과가 'confirmed' 인 경우의 수를 새로운 칼럼 confirmed_count 에 넣어주는 쿼리이다. 

89번. Managers with at Least 5 Direct Reports

  • 나의 정답 코드
WITH managers AS(
SELECT managerId 
	FROM Employee
	GROUP BY managerId 
	HAVING COUNT(managerId )>=5)

SELECT name
FROM Employee
WHERE id IN (SELECT * FROM managers);

  • 나의 오답 코드
SELECT name
FROM Employee 
WHERE id = (
    SELECT 
    CASE WHEN COUNT(name) >= 5 THEN managerId
    ELSE NAME END AS "NAME"
    FROM Employee 
    WHERE managerId IS NOT NULL 
    GROUP BY managerId)

서브쿼리가 하나 이상의 행을 반환하기 때문에 runtime error가 발생했다.
하나 이상의 행을 반환한 이유는 group by managerId와 case절의 else 부분 때문이다.

group by로 managerId 칼럼에 있는 모든 값에 대한 그룹핑(n개 그룹 생성)을 실시하고, 각 그룹에 대하여 case when ~ else(조건에 충족하지 않으면 Name을 반환하라고 명령했다.)을 시행하였기에 복수 개의 행이 반환되었다.

where 절 필터링 좌항값 id 와 달리 우항값이 복수개이기 때문에 발생한 오류라고 할 수 있다.


  • SELF JOIN 정답
select e.name from Employee e join Employee m on e.id = m.managerId
group by m.managerId having count(m.managerId)>=5

위 코드는, employee 태이블을 두 번 조인하여 같은 테이블에 존재하는 두 개의 칼럼을 비교하여 문제를 풀어냈다.

훨씬 쉽고 간단하게 풀리며 runtime 면에서 압도적으로 빠른 코드이다.

90번.confirmation rate

#오답 코드
select 
    s.user_id,
    count(case when action = 'confirmed' then 1 else 0 end)/count(action) as confirmation_rate # COUNT() 행을 
from Signups as s left join Confirmations as c on s.user_id= c.user_id 
group by s.user_id


# 정답코드
select 
    s.user_id,
    round(avg(if(c.action='confirmed',1,0)),2) as confirmation_rate #그룹별 평균을 구함.
from Signups as s left join Confirmations as c on s.user_id= c.user_id 
group by s.user_id

count() 함수에게 뒤통수 얼얼하게 맞은 그 문제,
튜터님께 물어보니 현업에서 2~3일동안 현업 분석가들도 회의하다가
아! count 때문이네!!! 라고 한 적도 있다고 한다.

count()는 "행"의 숫자를 세는 함수다.
그 행에 저장된 값이 0이라면 count()값의 결과는 1이다.
계산이 필요한 함수에서 count()를 사용하면 안된다.

0개의 댓글