여러 가지 숫자 형태에 공백을 넣으면 어떤 일이 벌어질까요?

한 번 알아보도록 하죠~

1. 먼저 테이블을 생성합니다.

CREATE TABLE TB_NumberTest

(

SEQ INT IDENTITY(1,1) NOT NULL,

DATATYPE VARCHAR(200) NOT NULL,

ColBigInt BIGINT,

ColBit BIT,

ColDecimal DECIMAL(5,2),

ColInt INT,

ColMoney MONEY,

ColNumeric NUMERIC(5,2),

ColSmallInt SMALLINT,

ColSmallMoney SMALLMONEY,

ColTinyInt TINYINT,

ColFloat FLOAT,

ColReal REAL

)

GO

2. 하나씩 INSERT 합니다. 간혹 오류가 나는 것도 있네요.

INSERT INTO TB_NumberTest (DATATYPE, ColBigInt) VALUES ('ColBigInt', '');

(1 row(s) affected)

INSERT INTO TB_NumberTest (DATATYPE, ColBit) VALUES ('ColBit', '');

(1 row(s) affected)

INSERT INTO TB_NumberTest (DATATYPE, ColDecimal) VALUES ('ColDecimal', '');

Msg 8114, Level 16, State 5, Line 1

Error converting data type varchar to numeric.

INSERT INTO TB_NumberTest (DATATYPE, ColInt) VALUES ('ColInt', '');

(1 row(s) affected)

INSERT INTO TB_NumberTest (DATATYPE, ColMoney) VALUES ('ColMoney', '');

(1 row(s) affected)

INSERT INTO TB_NumberTest (DATATYPE, ColNumeric) VALUES ('ColNumeric', '');

Msg 8114, Level 16, State 5, Line 1

Error converting data type varchar to numeric.

INSERT INTO TB_NumberTest (DATATYPE, ColSmallInt) VALUES ('ColSmallInt', '');

(1 row(s) affected)

INSERT INTO TB_NumberTest (DATATYPE, ColSmallMoney) VALUES ('ColSmallMoney', '');

(1 row(s) affected)

INSERT INTO TB_NumberTest (DATATYPE, ColTinyInt) VALUES ('ColTinyInt', '');

(1 row(s) affected)

INSERT INTO TB_NumberTest (DATATYPE, ColFloat) VALUES ('ColFloat', '');

(1 row(s) affected)

INSERT INTO TB_NumberTest (DATATYPE, ColReal) VALUES ('ColReal', '');

(1 row(s) affected)

3. 이제 결과를 보겠습니다.

SELECT * FROM TB_NumberTest;

numbertype.jpg

l 보시는 바와 같이 Numeric Type Decimal Type을 제외하고는 에러가 나지 않고 다 0으로 들어갑니다.

작업할 때 혼돈이 없도록 해야겠죠?

참고로… MSSQL에서 DECIMAL NUMERIC은 같은 타입입니다.

또, 참고로 Oracle에서는 숫자타입에 '' 을 넣으면 NULL로 처리됩니다.


아시는 분들은 잘 아시겠지만, 초보 분들을 위해...

LEFT OUTER JOIN 에 대해 그냥 실험하듯이 몇 가지를 해 보았습니다.

그냥 재미로 보시면 될 듯 하네요.

먼저 테이블을 두 개 만들어 보겠습니다.

CREATE TABLE dbo.TB_A

(SEQ1 INT,

DATA1 VARCHAR(1000)

);

CREATE TABLE dbo.TB_B

(SEQ2 INT,

DATA2 VARCHAR(1000)

);

SEQ1, DATA1 SEQ2, DATA2 로 되어 있는 간단한 테이블입니다.

여기에 데이터를 삽입합니다.

INSERT INTO TB_A VALUES (1,'테이블A1'), (2,'테이블A2'), (3,'테이블A3'), (4,'테이블A4'), (5,'테이블A5');

INSERT INTO TB_B VALUES (1,'테이블B1'), (3,'테이블B3'), (5,'테이블B5');

1번 테이블엔 다섯 개의 Row, 2번 테이블엔 세 개의 Row가 있습니다.

1. INNER JOIN해 보면 다음과 같습니다.

1.jpg

SELECT A.*, B.*

FROM TB_A A INNER JOIN TB_B B ON A.SEQ1 = B.SEQ2

당연히 세 개의 결과만 나오죠.

2. 그럼 LEFT OUTER JOIN에서 위와 같은 조건으로 해봅니다.

2.jpg

SELECT A.*, B.*

FROM TB_A A LEFT OUTER JOIN TB_B B ON A.SEQ1 = B.SEQ2

, 첫번째 테이블의 모든 것과 두번째 테이블에서 SEQ2이 매치되는 것만 보여주죠. 당연한 이야기입니다.

3. 그럼 이제 조건을 좀 바꿔보겠습니다.

3.jpg

SELECT A.*, B.*

FROM TB_A A LEFT OUTER JOIN TB_B B ON A.SEQ1 = B.SEQ2

WHERE A.DATA1 LIKE'%4'

테이블 14가 들어간 Row는 하나 뿐이므로WHERE 조건에 일치하는 것을 먼저 가져오고 나니 두 번째 테이블엔 매치되는 게 없습니다.

4. 그렇다면 저것을 JOIN 조건으로 올리게 되면 어떻게 될까요?

4.jpg

SELECT A.*, B.*

FROM TB_A A LEFT OUTER JOIN TB_B B ON A.SEQ1 = B.SEQ2 AND A.DATA1 LIKE '%4'

아까랑 많이 다릅니다. 이는 일단 기본적으로 테이블1에 있는 모든 것을 가져온 뒤 조건에 맞는 것을 찾기 때문입니다.

5. 그럼, 조건에 맞는 것이 있을 때는 어떻게 될까요?

6.jpg

SELECT A.*, B.*

FROM TB_A A LEFT OUTER JOIN TB_B B ON A.SEQ1 = B.SEQ2 AND B.DATA2 LIKE '%3'

이제 좀 달라졌죠? JOIN조건에 맞는 것이 없을 때와 있을 때는 위와 같이 차이가 납니다.

6. 4.번과 다른 조건으로 한 번 더 봅니다.

5.jpg

SELECT A.*, B.*

FROM TB_A A LEFT OUTER JOIN TB_B B ON A.SEQ1 = B.SEQ2 AND B.DATA2 LIKE '%4'

어라? 결과가 4번과 같습니다이는 결국 테이블2에서 매치되는 조건이 없기 때문입니다.

7. 가장 주의해야 할 사항은 지금 보여드리는 쿼리입니다.

7.jpg

SELECT A.*, B.*

FROM TB_A A LEFT OUTER JOIN TB_B B ON A.SEQ1 = B.SEQ2

WHERE B.DATA2 LIKE'%3'

LEFT OUTER JOIN임에도 불구하고 두 번째 테이블의 컬럼 조건을 WHERE절에 쓰면

해당 조건에 맞는 데이터를 먼저 걸러내게 됩니다.

아마실제로 원했던 것은 5.번과 같이 먼저 첫번째 테이블의 모든 결과를 가져온 뒤, 두번째 테이블 조건에 일치하는 것을 찾으려고 했을 것입니다.

계속 쳐다보면 더 헷갈릴 수도 있으니원리를 찾아보시면 좋을 듯 합니다. ^^.


안녕하세요...

오늘은 CTE를 사용해서 복잡한 JOIN 구문을 좀 알기 쉽고 편리하게 처리해 볼까 합니다.

먼저 원문입니다.

SELECT

AA.SalesOrderID, AA.SalesLastYear, AA.Bonus, AA.Comment,

BB.AddressID, BB.CustomerID, BB.AccountNumber,

CC.SalesOrderID, CC.SalesPersonID, CC.ShipDate

FROM

(

SELECT

A.SalesOrderID, A.OrderDate, A.Comment, A.SalesPersonID, A.ShipDate, A.CustomerID,

B.Bonus, B.CommissionPct, B.SalesLastYear, B.SalesQuota

FROM Sales.SalesOrderHeader A, Sales.SalesPerson B

WHERE A.SalesPersonID = B.SalesPersonID

AND A.SalesOrderID >= 70000

) AA

LEFT OUTER JOIN

(SELECT

A.CustomerID, A.AccountNumber, A.CustomerType,

B.AddressID, B.AddressTypeID

FROM Sales.Customer A, Sales.CustomerAddress B

WHERE A.CustomerID = B.CustomerID

AND A.CustomerID >= 1 AND A.CustomerID <= 20

) BB

ON AA.CustomerID = BB.CustomerID

LEFT OUTER JOIN

(

SELECT

A.SalesOrderID, A.OrderDate, A.Comment, A.SalesPersonID, A.ShipDate, A.CustomerID,

B.SalesOrderDetailID, B.ProductID, B.OrderQty

FROM Sales.SalesOrderHeader A, Sales.SalesOrderDetail B

WHERE A.SalesOrderID = B.SalesOrderID

AND A.SalesOrderID >= 70000

) CC

ON AA.CustomerID = CC.CustomerID

;

보시는 바와 같이 굵은 줄 친 부분 글씨를 유심히 보지 않으면 JOIN 구문 찾기가 쉽지 않습니다. 이것이 CTE를 사용하지 않은 Sub Query 원문이고요.

만약 이것이 여러 개라면 더더욱 복잡해 지겠지요?

그러면 CTE를 사용해서 정리해 보겠습니다.

WITH AA

AS

(

SELECT

A.SalesOrderID, A.OrderDate, A.Comment, A.SalesPersonID, A.ShipDate, A.CustomerID,

B.Bonus, B.CommissionPct, B.SalesLastYear, B.SalesQuota

FROM Sales.SalesOrderHeader A, Sales.SalesPerson B

WHERE A.SalesPersonID = B.SalesPersonID

AND A.SalesOrderID >= 70000

),

BB AS

(SELECT

A.CustomerID, A.AccountNumber, A.CustomerType,

B.AddressID, B.AddressTypeID

FROM Sales.Customer A, Sales.CustomerAddress B

WHERE A.CustomerID = B.CustomerID

AND A.CustomerID >= 1 AND A.CustomerID <= 20

),

CC AS

(

SELECT

A.SalesOrderID, A.OrderDate, A.Comment, A.SalesPersonID, A.ShipDate, A.CustomerID,

B.SalesOrderDetailID, B.ProductID, B.OrderQty

FROM Sales.SalesOrderHeader A, Sales.SalesOrderDetail B

WHERE A.SalesOrderID = B.SalesOrderID

AND A.SalesOrderID >= 70000

)

SELECT

AA.SalesOrderID, AA.SalesLastYear, AA.Bonus, AA.Comment,

BB.AddressID, BB.CustomerID, BB.AccountNumber,

CC.SalesOrderID, CC.SalesPersonID, CC.ShipDate

FROM

AA LEFT OUTER JOIN BB ON AA.CustomerID = BB.CustomerID

LEFT OUTER JOIN CC ON AA.CustomerID = CC.CustomerID

;

각각 With로 시작하고,

Alias와 , 를 사용한 것 외에는 별 다를 것이 없지만.

FROM 절 아래로 JOIN 구문을 내림으로써 훨씬 보게 좋게 JOIN 확인이 가능합니다. ^^.

간단한 팁이지만, 부득이하게 Sub Query가 많아질 경우 JOIN 관계를 알아보기 힘들게 되므로,

이럴 때 쓰시면 편리하실 듯 하네요. ^^

이상입니다.


* Oracle START WITH ~ CONNECT BY MSSQL 처리하기.

 

# Oracle

SELECT   LEVEL, CATE_ID, LTRIM (SYS_CONNECT_BY_PATH (CATE_NAME, ' > '), ' > ') || ' > ' AS CATE_NAME

      FROM TBL_CATEGORY

START WITH CATE_ID = 1

CONNECT BY PRIOR CATE_ID = PARENT_CATE_ID

 

 

 

# SQL Server

WITH CTE_TABLE

AS

(

       SELECT 1 AS LEVEL, A.CATE_ID, PARENT_CATE_ID, CATE_NAME, CONVERT(VARCHAR(100), CAST(A.CATE_NAME as VARCHAR(100)) + ' > ') AS CATE_NAME

       FROM dbo.TBL_CATEGORY A

       WHERE A.CATE_ID = 1

 

       UNION ALL

      

       SELECT LEVEL + 1, M.CATE_ID, M.PARENT_CATE_ID, M.CATE_NAME, CONVERT(VARCHAR(100), N.CATE_NAME + ' > ' + CAST(M.CATE_NAME AS VARCHAR(100)) + ' > ' ) AS CATE_NAME

       FROM dbo.TBL_CATEGORY M JOIN CTE_TABLE N ON M.PARENT_CATE_ID = N.CATE_ID

)

SELECT * FROM CTE_TABLE

;

+ Recent posts