MS SQL Server에서
ROUND함수는 기본적으로 숫자를 지정된 소수 자릿수로 반올림만틈만 하고, 그 뒤의 자릿수를 제거하지 않는 경우가 있다.
이 문제를 해결하려면 출력 형식을 명확히 제어해야 한다.
그니까 간단히 말하자면
- ROUND(~, 2) 이런식으로 하면
42850.0400000000 47381.4800000000
이렇게 밖에 안 나옴 깔끔하게 두번째 자리까지 나오는게 아님.
두번째 자리까지 나오게 하려면
CAST를 활용하든지,Format을 활용하든지 해야함.
그중Format이 길지 않고 간결하므로 이하에서는FORMAT을 사용... 하고자 하였으나
FORMAT 함수의 경우문자열을 뱉어냄... 그래서그냥CAST쓰기로 함...- 요약하자면 아래 두 쿼리가 다른 거임! 하나는 문자열 하나는 숫자!
SELECT FORMAT(ROUND((SUM(LAT_N)), 2), 'N2'), FORMAT(ROUND((SUM(LONG_W)), 2), 'N2')
FROM STATION;
# 42,850.04 47,381.48 >> 문자열
SELECT
CAST(ROUND(SUM(LAT_N), 2) AS NUMERIC(10, 2)) AS Sum_Latitude,
CAST(ROUND(SUM(LONG_W), 2) AS NUMERIC(10, 2)) AS Sum_Longitude
FROM STATION;
# 42850.04 47381.48 >> 숫자
CAST(expression AS data_type)
expression: 변환하려는 값(숫자, 문자열, 날짜 등).data_type: 변환하려는 대상 데이터 타입(예: INT, DECIMAL, VARCHAR, DATETIME 등).CAST는 모든 SQL 표준을 지원하는 DBMS에서 사용 가능.소수점 이하 2자리까지만 표시:
SELECT CAST(123.4567 AS DECIMAL(10, 2)) AS RoundedValue;
결과:
| RoundedValue |
|---|
| 123.46 |
숫자로 변환 가능한 문자열을 숫자로 변환:
SELECT CAST('12345' AS INT) AS NumericValue;
결과:
| NumericValue |
|---|
| 12345 |
숫자를 문자열로 변환하여 특정 형식 출력:
SELECT CAST(12345 AS VARCHAR(10)) AS StringValue;
결과:
| StringValue |
|---|
| 12345 |
날짜 데이터를 문자열로 변환:
SELECT CAST(GETDATE() AS VARCHAR(20)) AS DateAsString;
결과:
| DateAsString |
|---|
| 2024-12-12 13:45:00 |
날짜 형식의 문자열을 실제 날짜 데이터로 변환:
SELECT CAST('2024-12-12' AS DATE) AS DateValue;
결과:
| DateValue |
|---|
| 2024-12-12 |
소수점을 특정 자리까지 제한(숫자 데이터 유지):
SELECT CAST(ROUND(123.456789, 2) AS DECIMAL(10, 2)) AS RoundedValue;
결과:
| RoundedValue |
|---|
| 123.46 |
CAST와 관련된 데이터 타입숫자형: INT, FLOAT, DECIMAL(precision, scale)
DECIMAL(precision, scale): precision: 전체 자리 수. scale: 소수점 아래 자리 수.DECIMAL(10, 2) → 최대 10자리, 소수점 이하 2자리.문자형: CHAR(n), VARCHAR(n)
n은 최대 문자 길이.날짜/시간형: DATE, DATETIME, TIME
이진형: BINARY, VARBINARY
CAST와 CONVERT의 차이CAST:CONVERT:SELECT CONVERT(VARCHAR, GETDATE(), 103) AS FormattedDate;결과: 12/12/2024SELECT CAST(ROUND(SUM(LAT_N), 2) AS NUMERIC(10,2)), CAST(ROUND(SUM(LONG_W), 2) AS NUMERIC(10,2))
FROM STATION;
SELECT CAST(SUM(LAT_N) AS NUMERIC(10,4))
FROM STATION
WHERE LAT_N > 38.7880
AND LAT_N < 137.2345;
MS SQL Server에는 TRUNC 같은 함수는 없다. CAST로 대부분 처리하거나 ROUND CEILNG, FLOOR로 처리
SELECT CAST(MAX(LAT_N) AS NUMERIC(10,4))
FROM STATION
WHERE LAT_N < 137.2345;
SELECT TOP 1 CAST(ROUND(LONG_W,4) AS NUMERIC(10,4))
FROM STATION
WHERE LAT_N = (SELECT MAX(LAT_N) FROM STATION WHERE LAT_N < 137.2345);
이건 문제가 말이 좀 어려웠다...
SELECT CAST(ROUND(MIN(LAT_N), 4) AS NUMERIC(10, 4))
FROM STATION
WHERE LAT_N > 38.7780;
SELECT TOP 1 CAST(ROUND(LONG_W, 4) AS NUMERIC(10,4))
FROM STATION
WHERE LAT_N = (SELECT MIN(LAT_N) FROM STATION WHERE LAT_N > 38.7780);
SELECT CAST(ROUND((MAX(LAT_N) + MAX(LONG_W) - MIN(LAT_N) - MIN(LONG_W)), 4) AS NUMERIC(10,4))
FROM STATION;
SELECT CAST(SQRT(POWER(MAX(LAT_N) - MIN(LAT_N), 2) + POWER(MAX(LONG_W) - MIN(LONG_W), 2)) AS NUMERIC(10,4))
FROM STATION;
POWER => 제곱
SQRT => 루트
WITH NUM_PLUS AS (
SELECT LAT_N, ROW_NUMBER() OVER (ORDER BY LAT_N) AS RowAsc
FROM STATION
)
SELECT CAST(ROUND(LAT_N, 4) AS NUMERIC(10,4))
FROM NUM_PLUS
WHERE RowAsc = CEILING(COUNT(RowAsc)/2);
2.0으로 나누는 거랑 2로 나누는거랑 다릅니다 ~ 정수를 정수로 나누면 정수가 나옵니다~ 그니까 실수로 나눠줘요 홀수로 떨어질때 제대로 중앙값 구할 수 있어요~WITH NUM_PLUS AS (
SELECT LAT_N, ROW_NUMBER() OVER (ORDER BY LAT_N) AS RowAsc
FROM STATION
)
SELECT CAST(ROUND(LAT_N, 4) AS NUMERIC(10,4))
FROM NUM_PLUS
WHERE RowAsc = (SELECT CEILING(COUNT(*)/2.0)
FROM STATION);
그니까 위에가 맞지
아래는 틀렸습니다~
WITH NUM_PLUS AS (
SELECT LAT_N, ROW_NUMBER() OVER (ORDER BY LAT_N) AS RowAsc
FROM STATION
)
SELECT CAST(ROUND(LAT_N, 4) AS NUMERIC(10,4))
FROM NUM_PLUS
WHERE RowAsc = (SELECT CEILING(COUNT(*)/2)
FROM STATION);
CASE문에서DESC, ASC같은 정렬지시자는 사용 불가하다.
그래서 아래와 같은 query는 안 된다.
SELECT CASE
WHEN G.Grade < 8 THEN 'NULL'
ELSE S.NAME
END,
G.Grade,
S.Marks
FROM Students AS S, Grades AS G
WHERE S.MarkS >= G.Min_Mark
AND S.MarkS <= G.Max_Mark
ORDER BY CASE
WHEN G.Grade >= 8 THEN G.Grade DESC, NAME
ELSE G.Grade DESC, S.Marks ASC
END;
# Msg 156, Level 15, State 1, Server dbrank-tsql, Line 17
# Incorrect syntax near the keyword 'DESC'.
그래서 다음과 같은 식으로 해줘야 한다...?
SELECT CASE
WHEN G.Grade < 8 THEN 'NULL'
ELSE S.NAME
END,
G.Grade,
S.Marks
FROM Students AS S, Grades AS G
WHERE S.MarkS >= G.Min_Mark
AND S.MarkS <= G.Max_Mark
ORDER BY G.Grade DESC, CASE
WHEN G.Grade >=8 THEN S.NAME
ELSE S.Marks
END;
그런데 이렇게 하면 에러난다 ;;;
CASE문의 반환값은 항상 같은 Type을 가져야하기 때문... 헐 ;;
그래서 CASE문을 따로 나눠서 넣어줘야한다...
SELECT CASE
WHEN G.Grade < 8 THEN 'NULL'
ELSE S.NAME
END,
G.Grade,
S.Marks
FROM Students AS S, Grades AS G
WHERE S.MarkS >= G.Min_Mark
AND S.MarkS <= G.Max_Mark
ORDER BY G.Grade DESC, CASE
WHEN G.Grade >=8 THEN S.NAME
ELSE NULL
END,
CASE
WHEN G.Grade < 8 THEN S.Marks
ELSE NULL
END;
ELSE NULL은 없어도 암묵적으로 작동하나, 가시성 및 의도를 명확히 반영하기 위해 NULL로 처리해주었다.