[MSSQL] 2000 VS 2005 : Group by, Max

2007. 11. 7. 16:29Coders

MSSQL 2000 과 2005 의 차이점... 이라기 보다는,
새로이 출시된 MSSQL 2005 에서는 가능하지만, 2000에서는 불가능(실행할 수 없는)한
코드에 대한 이야기이다.
아직까지 신제품인 2005 버전보다, 2000 버전을 사용하는 경우가 많으니, 이는 한번 살펴봄 직 하다.
(아니, 쿼리 자체가 전혀 사용될 만한 게 아닌가?)
SSMS 에서 다음 소스를 실행해 보자.
(SSMS : Sql Server Management Studio 의 약자. 누군가 계속 에스에스엠에스 라고 떠드는 것 보니, 이 약어는 기본적 소양인가 보다.)

  1. CREATE TABLE TBL_TEST
  2. (
  3.     CODE   NVARCHAR(4),
  4.     QT     NUMERIC(17,0)
  5. )
  6. GO
  7.  
  8. DECLARE @LOOP        INT,
  9.         @CODEPREFIX  NVARCHAR(10),
  10.         @CODE        NVARCHAR(4)
  11.  
  12. SET @LOOP = 1
  13. SET @CODEPREFIX = 'ABCDEFGHIJ'
  14.  
  15. SET NOCOUNT ON
  16. WHILE @LOOP <= 100
  17. BEGIN
  18.   SET @CODE = SUBSTRING(@CODEPREFIX, @LOOP % 10 + 1, 1) +
  19.               RIGHT(REPLICATE('0', 3) + CAST(@LOOP AS NVARCHAR), 3)
  20.   INSERT TBL_TEST(CODE, QT)
  21.   VALUES ( @CODE, CAST(RAND() * 1000000 AS NUMERIC(17,0)) )
  22.   SET @LOOP = @LOOP + 1
  23. END
  24. SET NOCOUNT OFF
  25.  
  26. /* ① 시작코드별로 GROUPING, SUM, 나머지 자리의 MAX 값 조회 */
  27. /* MS-SQL 2000 / 2005 에서 둘 다 실행 가능                  */
  28. SELECT LEFT(CODE, 1) AS CODE_PREFIX,
  29.        MAX(RIGHT(CODE, 3)) AS MAX_POSTFIX,
  30.        SUM(ISNULL(QT, 0)) AS QT_SUM
  31.   FROM TBL_TEST
  32.  GROUP BY LEFT(CODE, 1)
  33.  ORDER BY LEFT(CODE, 1)
  34. GO
  35.  
  36. /* ② 시작코드별로 GROUPING, SUM, 가장큰 코드값 조회      */
  37. /* MS-SQL 2000 에서 실행 불가능, 2005 에서는 실행 가능    */
  38. SELECT LEFT(CODE, 1) AS CODE_PREFIX,
  39.        LEFT(CODE, 1) + MAX(RIGHT(CODE, 3)) AS MAX_CODE,
  40.        SUM(ISNULL(QT, 0)) AS QT_SUM
  41.   FROM TBL_TEST
  42.  GROUP BY LEFT(CODE, 1)
  43.  ORDER BY LEFT(CODE, 1)
  44. GO
  45.  
  46. /* ③ 2000에서 실행되지 않는 ②의 쿼리를 실행시키는 INLINE VIEW */
  47. /* MS-SQL 2000 / 2005 에서 둘 다 실행 가능                      */
  48. SELECT CODE_PREFIX,
  49.        CODE_PREFIX + MAX_POSTFIX AS MAX_CODE,
  50.        QT_SUM
  51.   FROM (
  52.          SELECT LEFT(CODE, 1) AS CODE_PREFIX,
  53.                 MAX(RIGHT(CODE, 3)) AS MAX_POSTFIX,
  54.                 SUM(ISNULL(QT, 0)) AS QT_SUM
  55.            FROM TBL_TEST
  56.           GROUP BY LEFT(CODE, 1)
  57.        ) AS FOR_2000
  58.  ORDER BY CODE_PREFIX
  59. GO
  60.  
  61. DROP TABLE TBL_TEST
  62. GO

대충, 중간의 쿼리문은, 임시 테이블에 데이터를 채우는 것이니까 자세한 설명은 패스.
중요한 부분은 ② 의 다음 코드이다.

LEFT(CODE, 1) + MAX(RIGHT(CODE, 3))

보면, GROUPING 한 값과, MAX 값에 대한 문자열 합을 SELECT 한다.
문제는, 2005 에서는, 이에 대한 수행이 제대로 되지만,
2000 에서는 다음과 같은 오류를 뱉는다.

서버: 메시지 8120, 수준 16, 상태 1, 줄 4
'TBL_TEST.CODE' 열이 집계 함수나 GROUP BY 절에 없으므로 SELECT 목록에서 사용할 수 없습니다

이는 2000 버전이 멍청하다거나, 또는 2005 버전이 훨씬 좋아졌네를 말하고자 하는 것이 아니다.
그런 말도 있지 않은가 "틀린 것이 아닙니다. 다른 겁니다." ㅎㅎ
결과처리의 순서가 다르다고 볼 수 있겠다... 라기 보다는 연산에 관련된 문제인데,
뭐냐하면, GROUP 값과, MAX 값의 문자열을 더하는(Concatenation) 연산에서 앞 쪽의 GROUPING 대상 때문에 뒤쪽의 값 까지 영향을 받아 같은 GROUP BY 절에 없다고 뭐라 하는 것이다.
즉, 이상이 없던 2005 버전에서는, 각기 개별의 연산(GROUPING 과 MAX)을 실행한 후에 문자열을 더하고 있고, 2000 버전에서는 GROUPING 과 MAX 연산 이전에 문자열을 더하려고 하는???

시바, 잘 모르겠다.
아무튼, 저대로 실행된다. ( 2000에선 안된다고 하는 건 안된다고 나오고, 뭐 그렇다는 얘기...)