이유 ✅
UNION ALL을 하면 컬럼명이 첫 번째 SELECT 절을 기준으로 결정됨
즉, DATE_FORMAT(SALES_DATE, '%Y-%m-%d') AS SALES_DATE를 한쪽에서만 적용하면 다른 테이블과 UNION ALL할 때 데이터 타입이 맞지 않을 수 있음
일관된 컬럼 형식을 유지하려면 두 테이블에서 모두 변환 후 UNION ALL해야 함
SELECT DATE_FORMAT(ONS.SALES_DATE, '%Y-%m-%d') AS SALES_DATE,
ONS.PRODUCT_ID,
ONS.USER_ID,
ONS.SALES_AMOUNT
FROM ONLINE_SALE AS ONS
WHERE ONS.SALES_DATE BETWEEN '2022-03-01' AND '2022-03-31'
UNION ALL
SELECT DATE_FORMAT(OFS.SALES_DATE, '%Y-%m-%d') AS SALES_DATE,
OFS.PRODUCT_ID,
'NULL' AS USER_ID,
OFS.SALES_AMOUNT
FROM OFFLINE_SALE AS OFS
WHERE OFS.SALES_DATE BETWEEN '2022-03-01' AND '2022-03-31'
ORDER BY SALES_DATE, PRODUCT_ID, USER_ID;
SELECT DATE_FORMAT(SALES_DATE, '%Y-%m-%d') AS SALES_DATE,
PRODUCT_ID,
USER_ID,
SALES_AMOUNT
FROM (
SELECT SALES_DATE, PRODUCT_ID, USER_ID, SALES_AMOUNT
FROM ONLINE_SALE
WHERE SALES_DATE BETWEEN '2022-03-01' AND '2022-03-31'
UNION ALL
SELECT SALES_DATE, PRODUCT_ID, 'NULL' AS USER_ID, SALES_AMOUNT
FROM OFFLINE_SALE
WHERE SALES_DATE BETWEEN '2022-03-01' AND '2022-03-31'
) AS COMBINED_DATA
ORDER BY SALES_DATE, PRODUCT_ID, USER_ID;
✔ 서브쿼리를 사용하면 DATE_FORMAT을 한 번만 적용할 수 있음
✔ 하지만 불필요한 데이터까지 UNION ALL 후 필터링되므로 비효율적일 수도 있음
합치기 전에 날짜를 3월 BETWEEN AND 하지말고, 합친 후에 BETWEEN AND 를 WHERE 절에 쓰면 안돼?
SELECT DATE_FORMAT(SALES_DATE, '%Y-%m-%d') AS SALES_DATE,
PRODUCT_ID,
USER_ID,
SALES_AMOUNT
FROM (
SELECT SALES_DATE, PRODUCT_ID, USER_ID, SALES_AMOUNT
FROM ONLINE_SALE
UNION ALL
SELECT SALES_DATE, PRODUCT_ID, 'NULL' AS USER_ID, SALES_AMOUNT
FROM OFFLINE_SALE
) AS COMBINED_DATA
WHERE SALES_DATE BETWEEN '2022-03-01' AND '2022-03-31' -- ❌ 여기서 문제 발생!
ORDER BY SALES_DATE, PRODUCT_ID, USER_ID;
🚨 문제점
DATE_FORMAT(SALES_DATE, '%Y-%m-%d')을 적용하면 SALES_DATE가 문자열(VARCHAR)이 됨
그런데 WHERE SALES_DATE BETWEEN '2022-03-01' AND '2022-03-31'에서
👉 SALES_DATE는 이제 문자열이니까, 숫자로 된 날짜 비교(BETWEEN 연산)가 정확하게 동작하지 않을 수 있음!
날짜 비교는 DATE 타입으로 해야 정확함!
합친 후에 WHERE로 필터링하면 안 되는 이유!
네, 이 방식에서는 WHERE SALES_DATE BETWEEN '2022-03-01' AND '2022-03-31'을 UNION ALL 후에 적용하면 안 됩니다.
왜냐하면 SALES_DATE가 DATE_FORMAT()을 거친 후 문자열(VARCHAR)로 변환되기 때문이에요!
즉, WHERE절에서는 날짜가 3월로나오는데, SELECT 에서는 정작 문자열이니까 필터링이 안됨.
👉 WHERE SALES_DATE BETWEEN '2022-03-01' AND '2022-03-31'
👉 SALES_DATE가 DATE 타입이어야 날짜 비교가 정확하게 동작하는데, DATE_FORMAT()을 거친 후에는 문자열(VARCHAR)이 되니까 필터링이 안 될 수도 있어요!
결론: WHERE 필터링은 항상 DATE 타입 상태에서!
🚀 날짜 조건(BETWEEN)을 사용할 때는 항상 DATE 타입 상태에서 먼저 필터링하고, 그 후에 DATE_FORMAT()을 적용하자!
✅ 왜 이게 더 좋을까?
필터링을 먼저 하면 UNION ALL이 처리해야 할 데이터가 줄어들어 성능이 더 좋음!
👉 즉, 불필요한 데이터까지 UNION ALL 하지 않음
WHERE에서 DATE 타입으로 날짜 비교가 정확하게 동작함!
나중에 DATE_FORMAT()을 적용하더라도 날짜 비교 문제가 없음!
✅ 결론
서브쿼리 없이 UNION ALL 전에 각 테이블에서 DATE_FORMAT을 적용하는 것이 더 효율적
서브쿼리를 쓰면 DATE_FORMAT을 한 번만 적용할 수 있지만, 성능상 불리할 수도