COUNT
COUNT (개수)
지정된 열의 NULL이 아닌 레코드 수 또는 총 레코드 수를 반환해요.
본문
구문
집계 함수
COUNT( [ DISTINCT ] <expr1> [, <expr2> ... ] )
COUNT(*)
COUNT(<alias>.*)
윈도우 함수
COUNT( [ DISTINCT ] <expr1> [, <expr2> ... ] ) OVER (
[ PARTITION BY <expr3> ]
[ ORDER BY <expr4> [ { ASC | DESC } ] [ NULLS { FIRST | LAST } ] ]
[ <window_frame> ]
)
window_frame의 자세한 구문은 Window function syntax and usage를 참고해요.
인자
expr1
열 이름으로, 한정된 이름일 수 있어요(예: database.schema.table.column_name).
expr2
원한다면 추가 열 이름을 포함할 수 있어요. 예를 들어 성과 이름의 고유 조합 수를 셀 수 있어요.
expr3
결과를 여러 윈도우로 나누길 원하면 파티션할 열이에요.
expr4
각 윈도우를 정렬할 열이에요. 최종 결과 집합을 정렬하는 ORDER BY 절과는 별개란 점에 유의해요.
*
총 레코드 수를 반환해요.
함수에 와일드카드를 전달할 때 와일드카드를 테이블 이름이나 별칭으로 한정할 수 있어요. 예를 들어 mytable이라는 이름의 테이블에서 모든 열을 전달하려면 다음을 지정해요:
(mytable.*)
또한 필터링에 ILIKE 및 EXCLUDE 키워드를 사용할 수 있어요:
ILIKE는 지정된 패턴과 일치하는 열 이름을 필터링해요. 패턴은 하나만 허용돼요. 예:(* ILIKE 'col1%')EXCLUDE는 지정된 열과 일치하지 않는 열 이름을 필터링해요. 예:(* EXCLUDE col1),(* EXCLUDE (col1, col2))
이러한 키워드를 사용할 때 한정자(qualifiers)가 유효해요. 다음 예시는 ILIKE 키워드를 사용해 mytable 테이블에서 col1% 패턴과 일치하는 모든 열을 필터링해요:
(mytable.* ILIKE 'col1%')
ILIKE와 EXCLUDE 키워드는 단일 함수 호출에서 결합할 수 없어요.
한정되지 않고 필터링되지 않은 와일드카드(*)를 지정하면 함수는 NULL 값이 있는 레코드를 포함해 총 레코드 수를 반환해요.
필터링을 위해 ILIKE나 EXCLUDE 키워드가 있는 와일드카드를 지정하면 함수는 NULL 값이 있는 레코드를 제외해요.
이 함수의 경우 ILIKE와 EXCLUDE 키워드는 SELECT 목록이나 GROUP BY 절에서만 유효해요.
ILIKE 및 EXCLUDE 키워드에 대한 자세한 내용은 SELECT의 "Parameters" 섹션을 참고해요.
alias.*
NULL 값을 포함하지 않는 레코드 수를 반환해요. 예시는 Examples를 참고해요.
반환 값
NUMBER 타입의 값을 반환해요.
사용상 주의사항
- 이 함수는 JSON null(VARIANT NULL)을 SQL NULL로 취급해요.
- NULL 값과 집계 함수에 대한 자세한 내용은 Aggregate functions and NULL values를 참고해요.
- 이 함수가 집계 함수로 호출될 때: DISTINCT 키워드를 사용하면 모든 열에 적용돼요. 예를 들어
DISTINCT col1, col2, col3은 열col1,col2,col3의 서로 다른 조합 수를 반환함을 의미해요. 예를 들어 데이터가1,1,1/1,1,1/1,1,1/1,1,2라고 가정할 때, 이 경우 함수는 세 열에 있는 값의 서로 다른 조합 수인2를 반환해요. - 이 함수가 ORDER BY 절을 포함한 OVER 절을 가진 윈도우 함수로 호출될 때: 윈도우 프레임이 필수예요. 명시적으로 지정하지 않으면 다음의 암시적 윈도우 프레임이 사용돼요:
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW. 윈도우 프레임에 대한 자세한 내용은 Window function syntax and usage를 참고해요. - DISTINCT는 고유 집합이 단일 열에 적용될 때 ORDER BY를 포함한 OVER 절과 함께 사용할 수 있어요. 예:
COUNT(DISTINCT <expr>) OVER (... ORDER BY <orderexpr> [...]).COUNT(DISTINCT <expr1>, <expr2>, ...)같이 여러 열 표현식을 참조하는 고유 개수는 OVER 절에 ORDER BY도 포함되면 유효하지 않아요. - 조건과 일치하는 행 수를 반환하려면 COUNT_IF를 사용해요.
- 가능하면 행 접근 정책(row access policy)이 없는 테이블과 뷰에 COUNT 함수를 사용해요. 이 함수가 있는 쿼리는 행 접근 정책이 없는 테이블이나 뷰에서 더 빠르고 정확해요. 성능 차이의 이유는 Snowflake가 테이블과 뷰에 대한 통계를 유지하고, 이 최적화로 단순 쿼리를 더 빠르게 실행할 수 있기 때문이에요. 행 접근 정책이 테이블이나 뷰에 설정되어 있고 쿼리에서 COUNT 함수가 사용되면 Snowflake는 각 행을 스캔하고 사용자가 행을 볼 수 있는지 결정해야 해요.
예시
다음 예시들은 NULL 값이 있는 데이터에 COUNT 함수를 사용해요.
테이블을 만들고 값을 삽입해요:
CREATE TABLE basic_example (i_col INTEGER, j_col INTEGER);
INSERT INTO basic_example VALUES
(11, 101),
(11, 102),
(11, NULL),
(12, 101),
(NULL, 101),
(NULL, 102);
테이블 조회:
SELECT * FROM basic_example ORDER BY i_col;
+-------+-------+
| I_COL | J_COL |
|-------+-------|
| 11 | 101 |
| 11 | 102 |
| 11 | NULL |
| 12 | 101 |
| NULL | 101 |
| NULL | 102 |
+-------+-------+
SELECT COUNT(*) AS "All",
COUNT(* ILIKE 'i_c%') AS "ILIKE",
COUNT(* EXCLUDE i_col) AS "EXCLUDE",
COUNT(i_col) AS "i_col",
COUNT(DISTINCT i_col) AS "DISTINCT i_col",
COUNT(j_col) AS "j_col",
COUNT(DISTINCT j_col) AS "DISTINCT j_col"
FROM basic_example;
+-----+-------+---------+-------+----------------+-------+----------------+
| All | ILIKE | EXCLUDE | i_col | DISTINCT i_col | j_col | DISTINCT j_col |
|-----+-------+---------+-------+----------------+-------+----------------|
| 6 | 4 | 5 | 4 | 2 | 5 | 2 |
+-----+-------+---------+-------+----------------+-------+----------------+
이 출력의 All 열은 COUNT에 대해 한정되지 않고 필터링되지 않은 와일드카드를 지정하면 함수가 NULL 값이 있는 행을 포함해 테이블의 총 행 수를 반환함을 보여줘요. 출력의 다른 열은 열 또는 필터링이 있는 와일드카드를 지정하면 함수가 NULL 값이 있는 행을 제외함을 보여줘요.
다음 쿼리는 GROUP BY 절과 함께 COUNT 함수를 사용해요:
SELECT i_col, COUNT(*), COUNT(j_col)
FROM basic_example
GROUP BY i_col
ORDER BY i_col;
+-------+----------+--------------+
| I_COL | COUNT(*) | COUNT(J_COL) |
|-------+----------+--------------|
| 11 | 3 | 2 |
| 12 | 1 | 1 |
| NULL | 2 | 2 |
+-------+----------+--------------+
다음 예시는 COUNT(alias.*)가 NULL 값을 포함하지 않는 행 수를 반환함을 보여줘요. basic_example 테이블은 총 6행이지만, 3행은 적어도 하나의 NULL 값을 갖고, 나머지 3행은 NULL 값이 없어요.
SELECT COUNT(n.*) FROM basic_example AS n;
+------------+
| COUNT(N.*) |
|------------|
| 3 |
+------------+
다음 예시는 JSON null(VARIANT NULL)이 COUNT 함수에 의해 SQL NULL로 취급됨을 보여줘요.
SQL NULL과 JSON null 값을 모두 포함하는 데이터로 테이블을 만들고 삽입해요:
CREATE OR REPLACE TABLE count_example_with_variant_column (
i_col INTEGER,
j_col INTEGER,
v VARIANT
);
BEGIN WORK;
INSERT INTO count_example_with_variant_column (i_col, j_col, v)
VALUES (NULL, 10, NULL);
INSERT INTO count_example_with_variant_column (i_col, j_col, v)
SELECT 1, 11, PARSE_JSON('{"Title": null}');
INSERT INTO count_example_with_variant_column (i_col, j_col, v)
SELECT 2, 12, PARSE_JSON('{"Title": "O"}');
INSERT INTO count_example_with_variant_column (i_col, j_col, v)
SELECT 3, 12, PARSE_JSON('{"Title": "I"}');
COMMIT WORK;
이 SQL 코드에서 다음에 유의해요:
- 첫 번째 INSERT INTO 문은 VARIANT 열과 비-VARIANT 열 모두에 SQL NULL을 삽입해요.
- 두 번째 INSERT INTO 문은 JSON null(VARIANT NULL)을 삽입해요.
- 마지막 두 INSERT INTO 문은 NULL이 아닌 VARIANT 값을 삽입해요.
데이터 표시:
SELECT i_col, j_col, v, v:Title
FROM count_example_with_variant_column
ORDER BY i_col;
+-------+-------+-----------------+---------+
| I_COL | J_COL | V | V:TITLE |
|-------+-------+-----------------+---------|
| 1 | 11 | { | null |
| | | "Title": null | |
| | | } | |
| 2 | 12 | { | "O" |
| | | "Title": "O" | |
| | | } | |
| 3 | 12 | { | "I" |
| | | "Title": "I" | |
| | | } | |
| NULL | 10 | NULL | NULL |
+-------+-------+-----------------+---------+
COUNT 함수가 NULL과 JSON null(VARIANT NULL) 값을 모두 NULL로 취급함을 보여줘요. 테이블에는 네 행이 있어요. 하나는 SQL NULL이고 다른 하나는 JSON null이에요. 두 행 모두 개수에서 제외되므로 개수는 2예요.
SELECT COUNT(v:Title)
FROM count_example_with_variant_column;
+----------------+
| COUNT(V:TITLE) |
|----------------|
| 2 |
+----------------+
OVER 절과 함께 COUNT(DISTINCT …)를 사용해 시간에 따른 고유 고객 수 계산:
CREATE OR REPLACE TABLE customer_product_sales_fct (
sale_date DATE,
sale_id INTEGER,
customer_id STRING,
product_id STRING,
quantity INTEGER,
sales_amount NUMBER(10, 2)
);
INSERT INTO customer_product_sales_fct VALUES
('2026-01-01', 1, 'C001', 'P100', 1, 19.99),
('2026-01-02', 2, 'C002', 'P100', 2, 39.98),
('2026-01-03', 3, 'C001', 'P100', 1, 19.99),
('2026-01-04', 4, 'C003', 'P100', 1, 19.99),
('2026-01-05', 5, 'C002', 'P200', 1, 9.99),
('2026-01-06', 6, 'C004', 'P100', 3, 59.97),
('2026-01-07', 7, 'C003', 'P100', 1, 19.99),
('2026-01-08', 8, 'C005', 'P100', 2, 39.98),
('2026-01-09', 9, 'C001', 'P200', 1, 9.99),
('2026-01-10', 10, 'C006', 'P100', 1, 19.99);
SELECT
product_id,
customer_id,
sale_date,
sale_id,
COUNT(DISTINCT customer_id) OVER (
PARTITION BY product_id
ORDER BY sale_date
) AS distinct_customers_to_date
FROM customer_product_sales_fct
WHERE product_id = 'P100'
ORDER BY sale_date, sale_id;
+------------+-------------+------------+---------+----------------------------+
| PRODUCT_ID | CUSTOMER_ID | SALE_DATE | SALE_ID | DISTINCT_CUSTOMERS_TO_DATE |
+------------+-------------+------------+---------+----------------------------+
| P100 | C001 | 2026-01-01 | 1 | 1 |
| P100 | C002 | 2026-01-02 | 2 | 2 |
| P100 | C001 | 2026-01-03 | 3 | 2 |
| P100 | C003 | 2026-01-04 | 4 | 3 |
| P100 | C004 | 2026-01-06 | 6 | 4 |
| P100 | C003 | 2026-01-07 | 7 | 4 |
| P100 | C005 | 2026-01-08 | 8 | 5 |
| P100 | C006 | 2026-01-10 | 10 | 6 |
+------------+-------------+------------+---------+----------------------------+
더 알아보기
- Aggregate functions (General) — 집계 함수 모음
- COUNT_IF — 조건 개수
- SUM — 합계