https://www.hackerrank.com/challenges/weather-observation-station-4/problem?isFullScreen=true

 

Weather Observation Station 4 | HackerRank

Find the number of duplicate CITY names in STATION.

www.hackerrank.com

 

문제설명 : 

STATION 테이블에서 중복된 CITY 이름의 개수를 구하는 문제입니다.  정확히 설명하자면 전체 CITY 개수고유한 CITY 개수를 각각 계산하고 그 차이를 구하는 문제입니다.

 

내가 작성한 코드 (틀린 코드) : 

SELECT COUNT(CITY), COUNT(DISTINCT CITY) AS DISTINCT_CITY, DIFFERENCE
FROM STATION
WHERE COUNT(CITY) - COUNT(DISTINCT) = DIFFERENCE;

 

틀린 이유 : 

  • COUNT() 함수를  WHERE 절에 사용하였습니다.
  • WHERE 절에서 STATION 테이블에 없는 DIFFERENCE를 사용하였습니다.(재창조 하였다고 보면 됨.. 무에서 유 ^.^)
  • COUNT()  함수로 개수를 구해서 중복된 값을 빼는건 알았는데 각 절들의 구조를 이해하지 못한채로 우겨넣었습니다.

정답코드 :

SELECT COUNT(CITY) - COUNT(DISTINCT CITY) AS DIFFERENCE
FROM STATION;

 

배운점 :

  • COUNT() 함수는 집계함수 이기 때문에 WHERE 절에 사용할 수 없다.
  • 집계함수는 그룹화 된 데이터나 전체 데이터에 대해서만 작업하므로 WHERE절이 아닌 HAVING 절에서 조건을 걸어야한다. 
  • WHERE 절에 적을 수 있는 것은  FROM 절에서 지정한 테이블의 칼럼이 사용가능하다. 
  • 별칭은 SELECT 절에서만 정의되며, 그 값을 기준으로 필터링 할땐  WHERE 절을 사용해야 한다. 

DISTINCT 키워드

  • 중복된 값을 제거할때 사용한다.
  • 예를들어 tSite에 회원가입된 사용자들의 지역 목록을 가져올때 사용할 수 있다. 

[ tSite 테이블 ]

NAME AGE REGION
김영희 23 서울
이철수 18 대전
오미자 33 대전
안지혁 20 부산
박지수 27 강원

 

SELECT DISTINCT region FROM tSite;
REGION
서울
대전
부산 
강원

 

SQL Server vs Oracle 중복 처리방식 차이

SQL Server는 DISTINCT를 적용할 때 자동으로 정렬을 수행하면서 중복을 제거한다.

Oracle은 DISTINCT를 적용할 때 별도로 정렬하지 않고, 단순히 중복만 제거한다.

=> 중복 제거 후 순서를 정렬하기 위해선 ORDER BY를 쓰는 습관을 들이는게 좋다고 생각한다. 

 

 

COUNT함수에서의 DISTINCT 사용

위의 tSite 예제에서 고유한 지역의 개수를 알고싶다면

SELECT COUNT(DISTINCT REGION) AS "중복되지 않은 지역의 수" FROM tSite;

 

중복되지 않은 지역의 수
4

 

SQL에서 GROUP BY 와 집계함수 (COUNT(), SUM(), AVG(), MAX(), MIN())를 사용할 때 헷갈렸던 경험을 정리하였다.

처음에는 집계함수가 어떤 순서로 실행되는지, 그리고 왜 HAVING 과 WHERE 을 적절히 구분해야하는지 혼동했었다.

 

  1. 문제의 시작 :
    1. 문제는 WHERE 절에서 왜 집계함수를 사용할 수 없는지 이해하는데서 시작되었다.
    2. SQL에서 WHERE 절은 데이터를 필터링 하는데 쓰이는데, 집계함수는 데이터를 그룹화 한 후에 사용할 수 있기 때문에 WHERE에서는 사용할 수 없다는 사실을 몰랐었다.
  2. WHERE vs HAVING:
    1. WHERE 절은 그룹화되기 전에 조건을 걸기 때문에 집계 함수가 적용되지 않은 상태에서 데이터를 필터링할 수 있다.
    2. HAVING 절은 그룹화된 후에 조건을 걸기 때문에 집계 함수가 적용된 후에 조건을 걸고 싶을 때 사용할 수 있다.
  3. SQL 실행 순서:
1. FROM 데이터를 가져올 테이블을 선택한다.
2. WHERE 테이블에서 조건을 걸어서 데이터를 필터링한다.
3. GROUP BY 데이터를 그룹화하여 집계를 위한 단계를 만든다.
4. HAVING 그룹화된 데이터에 조건을 추가한다. (집계가 된 후)
5. SELECT 결과로 가져올 열을 선택한다.
6. ORDER BY 결과를 정렬한다.

 

[ 핵심은 GROUP BY ]

GROUP BY데이터를 집계하기 위해 필요한 단계이다. 이때 데이터를 그룹화 하는 작업이 이뤄지고, 집계함수를 적용할 수 있는 상태가 된다.

 

    4. 집계 함수와 그룹화:

  • 집계 함수는 데이터를 그룹화 한 후에 적용된다. 예를들어 COUNT(*)는 각 그룹별로 개수를 세는 함수이므로 데이터가 그룹화 되지 않으면 제대로 된 결과를 얻을 수 없다.
  • GROUP BY 는 데이터를 특정기준(ex. Country)으로 그룹화 라는 역할을 한다. 

 

    5. SQL 예시 분석:

SELECT Country, COUNT(*) AS Count
FROM Suppliers
GROUP BY Country
HAVING Count >= 3;
  • 위 예시에서 COUNT(*)GROUP BY로 그룹화 된 후에 계산되므로 위에서 설명했던 WHERE 절이 아닌 HAVING 절에서 그 값을 필터링 할 수 있다.
  • COUNT(*)는 각각의 Country 그룹에 대한 행의 개수를 세기 위한 함수인데 COUNT(*) 값이 3이상인 그룹만 선택하는 것이다.

 

   5. WHERE에서 집계함수를 사용하지 못하는 이유:

  • WHERE 절은 그룹화 되기 전에 실행되기 된다. 그러나 집계함수는 그룹화 된 후에 계산할 수 있기 때문에 WHERE 에서는 집계함수를 사용할 수 없다는 것을 알게되었다.

 

결론 : 

  • 집계함수는 항상 GROUP BY 절과 같이 쓰인다.
  • WHERE 에서는 데이터를 그룹화 하기 전의 상태에서만 필터링 할 수 있다.
  • 그룹화된 데이터에 조건을 걸고 싶으면 HAVING 을 사용해야 한다.

SQL에서 COUNT 함수는 특정 컬럼이나 테이블의 행 수를 셀 때 사용되지만, 사용 방식에 따라 결과가 달라질 수 있다.

내가 헷갈렸던 부분은 COUNT(*) 와 COUNT(컬럼)의 차이를 이해하는 것이였다.

 

예시 테이블 : Orders

OrderID CustomerID OrderDate
1 101 2025-03-01
2 102 NULL
3 103 2025-03-02
4 104 NULL
5 105 2025-03-03

 

 

1. COUNT(*) - 모든 행의 개수를 셈

  • COUNT(*) 는 테이블의 모든 행을 센다. 이때 NULL 값을 포함한 모든 행이 계산된다. 따라서 OrderDateNULL인 행도 포함해서 총 5개의 행을 센다.
SELECT COUNT(*) FROM Orders;

 

2. COUNT(OrderDate) – NULL을 제외한 값만 셈

  • COUNT(컬럼)은 지정한 컬럼에서 NULL이 아닌 값만 센다. OrderDateNULL인 두 개의 행은 제외하고, 나머지 3개OrderDate 값만 센다
SELECT COUNT(OrderDate) FROM Orders;

 

 

차이점 요약

COUNT(*): 테이블의 모든 행을 센다. NULL 값을 포함한 모든 행이 계산된다

COUNT(컬럼): 지정한 컬럼에서 NULL 값을 제외하고 계산한다. NULL이 아닌 값만 센다.

예제 : 매장별 판매 합계 구하기

 

Sales 테이블 :

Store SalesAmount
A 500
B 300
B 200
A 150
C 450

 

우리가 Store를 기준으로 그룹을 묶고, 각 그룹의 SalesAmount 값을 합산하고 싶다고 가정하자.

SELECT Store, SUM(SalesAmount) AS TotalSales
FROM Sales
GROUP BY Store
ORDER BY TotalSales DESC;

 

이 쿼리는 Sales 라는 테이블에서 각 가게의 총 판매 금액 합계를 구하는 쿼리이다.

 


[ GROUP BY ]

그 전에 GROUP BY 에 대해서 알아볼 필요가 있다. 

GROUP BY특정 컬럼을 기준으로 데이터를 그룹화 할때 사용한다.

GROUP BY Store는 Store 컬럼 값이 같은 데이터를 하나로 묶어서 그룹화 하는 것이다.

(ex. 'Z', 'Y', 'Z' 가 있었다면, 중복되는 Z와 Z는 하나의 그룹으로 묶이고 Y는 따로 그룹이 된다.)


 

쿼리 실행 순서와 과정 설명

  1. GROUP BY Store 로 그룹을 나누면 : 
    • 그룹 1: Store = 'A' (SalesAmount : 500, 150)
    • 그룹 2: Store = 'B' (SalesAmount : 300, 200)
    • 그룹 3: Store = 'C' (SalesAmount : 450)
  2. SUM(SalesAmount)로 각 그룹의 합을 구하면
    1. A : 500 + 150 = 650
    2. B : 300 + 200 500
    3. C : 450
  3. 결과는 이렇게 나온다 :
    1. Store = A, TotalSales = 650
    2. Store = B, TotalSales = 500
    3. Store = C, TotalSales = 450
  4. ODER BY TotalSales DESC 로 내림차순 정렬하면:
    1. Store = A, TotalSales = 650
    2. Store = B, TotalSales = 500
    3. Store = C, TotalSales = 450

최종 출력 결과 :

Store TotalSales
A 650
B 500
C 450

 


 

 

GROUP BY는 데이터를 그룹화하는 역할만 한다. 그래서 그룹화된 데이터에서 집계된 값을 얻고 싶을 때는 집계 함수(예: SUM, AVG, COUNT)를 사용해야 한다. 예를 들어, Store별로 각 판매 금액의 합계를 구하고 싶다면, SUM(SalesAmount)를 사용해서 각 그룹에 대해 판매 금액의 총합을 계산할 수 있다.

 

왜 SUM(Quantity)를 사용해야 할까?

GROUP BY만 사용하면 각 그룹이 나열되는 것만 확인할 수 있다. 그러나 각 그룹 내에서 합계나 평균 등을 계산하려면 SUM과 같은 집계 함수가 필요하다. 즉, GROUP BY는 그룹을 나누는 역할만 하고, 그룹 내에서 합산된 값이나 계산된 값을 구하기 위해선 집계 함수가 꼭 필요하다

[ 문제 ] : https://school.programmers.co.kr/learn/courses/30/lessons/131112

[ 요구사항 ]

  • 강원도에 위치한 식품공장의 공장 ID, 공장 이름, 주소를 조회하자.
  • 결과는 공장 ID를 기준으로 오름차순 정렬해야한다.

[ LIKE 연산자 ]

  • LIKE는 문자열 패턴 매칭을 위해 사용되는 연산자입니다. 이 연산자는 WHERE 절에서 주로 사용되며 특정 열(column)의 값이 특정 패턴과 일치하는지 확인하는 데 사용됩니다.
WHERE 컬럼명 LIKE '패턴';
  • 와일드카드(wildcard) 문자와 함께 사용하여 부분 문자열을 검색할 수 있습니다.

     < 와일드카드(Wildcards) >

  • % (퍼센트 기호): 0개 이상의 문자와 일치합니다.
  • '%강원도%' : ‘강원도’라는 문자열이 어디든 포함된 모든 값을 찾습니다.
  • 'A%' : ‘A’로 시작하는 모든 값을 찾습니다.
  • '%A' : ‘A’로 끝나는 모든 값을 찾습니다.
  • _ (밑줄) : 정확히 하나의 문자와 일치합니다.
  • '_angwon' : ‘angwon’이라는 단어에서 첫 글자만 제외한 단어와 일치하는 모든 값을 찾습니다.
  • 'A__' : ‘A’로 시작하고, 두 번째와 세 번째 문자가 어떤 문자든 상관없이 일치하는 값을 찾습니다.

 

문제에서는 "강원도" 에 위치한 주소를 찾아야하므로 %강원도% 를 사용하였습니다.


 

내가 사용한 방법:

  1. WHERE ADDRESS LIKE ‘%강원도%’: 강원도가 포함된 주소를 필터링했습니다.
  2. ORDER BY FACTORY_ID: 결과를 공장 ID 순으로 오름차순 정렬했습니다.

 

최종 SQL 쿼리

SELECT FACTORY_ID, FACTORY_NAME, ADDRESS
FROM FOOD_FACTORY
WHERE ADDRESS LIKE '%강원도%'
ORDER BY FACTORY_ID;

 

 

결과

이 쿼리의 실행 결과로 강원도에 위치한 식품공장의 공장 ID, 공장 이름, 주소가 공장 ID를 기준으로 오름차순 정렬되어 출력됩니다.

+ Recent posts