¾È±Ô °øºÎ¹æ

MS-SQL > °øÅë Å×ÀÌºí ½Ä(Common Table Expressions) °ú Àç±Í Äõ¸®

µî·ÏÀÏ : 2017-06-30 17:12 Á¶È¸¼ö : 52,594

°øÅë Å×ÀÌºí ½Ä(CTE) Àº ´Ü¼ø Äõ¸®·ÎºÎÅÍ ÆÄ»ýµÈ Àӽà °á°ú ÁýÇÕÀÔ´Ï´Ù.
CTE ´Â ÆÄ»ýµÈ Å×À̺íÀ» »ç¿ëÇÏ´Â °Íó·³, µ¿ÀÏÇÑ ¼ö´ÜÀ¸·Î »ç¿ë µÇ¾îÁú ¼ö ÀÖ½À´Ï´Ù. 
CTE´Â ¶ÇÇÑ Àڽſ¡ ´ëÇÑ ÂüÁ¶¸¦ Æ÷ÇÔÇÒ ¼ö ÀÖ½À´Ï´Ù. ÀÌ´Â µ¥ÀÌÅͺ£À̽º °³¹ßÀÚ°¡ Àç±Í Äõ¸®¸¦ ÀÛ¼ºÇÒ ¼ö ÀÖµµ·Ï ÇØÁÝ´Ï´Ù.
CTE ´Â ¶ÇÇÑ ºä ´ë½Å »ç¿ë µÇ¾îÁú ¼öµµ ÀÖ½À´Ï´Ù. °³³äÀûÀ¸·Î´Â ÀÓ½ÃÅ×À̺í°ú ºñ½ÁÇÕ´Ï´Ù.
´õ ÀûÀº ÄÚµå·Î ÀÓ½ÃÅ×À̺í, Àç±ÍÈ£ÃâµîÀ» ó¸®ÇÒ ¼ö ÀÖ½À´Ï´Ù.

±âÁ¸ SQL 2000 ¿¡¼­ »ç¿ë ÇÏ´ø ¹æ½Ä 

select SalesPersonID, count(*) as NumSales into #tmp 
    from Sales.SalesOrderHeader Group by SalesPersonID

select ts.SalesPersonID, sp.SalesYTD, ts.NumSales
    from Sales.SalesPerson sp inner join #tmp ts 
    on ts.SalesPersonID = sp.SalesPersonID
        order by NumSales Desc

SQL 2005ÀÇ CTE ¸¦ ÀÌ¿ëÇÑ ¹æ½Ä 

with TopSales    (SalesPersonID, NumSales) 
as 
    ( Select SalesPersonID, Count(*)
        From Sales.SalesOrderHeader Group BY SalesPersonID)

select ts.SalesPersonID, sp.SalesYTD, ts.NumSales
from Sales.SalesPerson sp inner join TopSales ts
    on ts.SalesPersonID = sp.SalesPersonID
        order by NumSales Desc


1.ÆÄ»ýµÈ Å×À̺í·Î »ç¿ëµÈ CTE ÇÊÅ͸µ Çϱâ

ºä·Î ¸®ÅÏµÈ °á°úÁýÇÕÀ» ÇÊÅ͸µÇÏ´Â °Í°ú ¸¶Âù°¡Áö·Î, ¿©·¯ºÐÀº °øÅë Å×ÀÌºí ½Ä(CTE) ¾È¿¡ Æ÷ÇÔµÈ °á°ú ÁýÇÕÀ» ÇÊÅ͸µ ÇÒ ¼ö ÀÖ½À´Ï´Ù.

WITH SalesCTE(ProductID , SalesOrderID)
AS 
(
    SELECT ProductID , COUNT(SalesOrderID)
        FROM Sales.SalesOrderDetail
            GROUP BY ProductID
)
SELECT * FROM SalesCTE WHERE SalesOrderID > 50 --50ȸÀÌ»óÁÖ¹®µÈ¸ðµçÁ¦Ç°µé

2.CTE ·Î Áý°èÇϱâ

°øÅë Å×ÀÌºí ½Ä(CTE) À¸·Î ¸®ÅÏµÈ µ¥ÀÌÅ͸¦ °¡Áö°í Áý°è ¶Ç´Â ±× ¹ÛÀÇ ´Ù¸¥ °è»êÀ» ¼öÇàÇÏ´Â °ÍÀº ±âº» Å×À̺í·ÎºÎÅÍ ¸®ÅÏµÈ µ¥ÀÌÅ͸¦ 
°¡Áö°í Áý°è ¹× ±âŸ °è»êÀ» ¼öÇàÇÏ´Â °Í°ú À¯»çÇÕ´Ï´Ù.

WITH SalesCTE(ProductID , SalesOrderID)
AS 
(
    SELECT ProductID , COUNT(SalesOrderID)
        FROM Sales.SalesOrderDetail
            GROUP BY ProductID
)
SELECT AVG(SalesOrderID) FROM SalesCTE WHERE SalesOrderID > 50

-- 50 ȸÀÌ»óÁÖ¹®µÈ¸ðµçÁ¦Ç°µéÀÇÆò±ÕÁÖ¹®È½¼ö

3. °øÅë Å×ÀÌºí ½Ä(CTE)À» »ç¿ëÇÏ´Â Àç±Í Äõ¸®

°øÅë Å×ÀÌºí ½Ä(CTE)ÀÇ ÁøÁ¤ÇÑ À§·ÂÀº Àç±Í Äõ¸®¸¦ ÀÛ¼ºÇÏ´Â µ¥¿¡ ÀÖ½À´Ï´Ù. 
°øÅë Å×ÀÌºí ½Ä(CTE) ÀÌ ÀÚ±â Àڽſ¡ ´ëÇÑ ÂüÁ¶°¡ °¡´ÉÇϱ⠶§¹®¿¡, Àç±Í Äõ¸®ÀÇ ÀÛ¼ºÀ» ºñ±³Àû °£´ÜÈ÷, ¼ö¿ùÇÏ°Ô ÇÒ ¼ö ÀÖ½À´Ï´Ù.

CREATE TABLE CarParts 
(
    CarID    int            NOT NULL
    ,    Part    varchar(15)
    ,    SubPart    varchar(15)
    ,    Qty        int
)
GO
INSERT CarParts VALUES(1 , 'Body' , 'Door' , 4)
INSERT CarParts VALUES(1 , 'Body' , 'Trunk Lid' , 1)
INSERT CarParts VALUES(1 , 'Body' , 'Car Hood' , 1)
INSERT CarParts VALUES(1 , 'Door' , 'Handle' , 1)
INSERT CarParts VALUES(1 , 'Door' , 'Lock' , 1)
INSERT CarParts VALUES(1 , 'Door' , 'Window' , 1)
INSERT CarParts VALUES(1 , 'Body' , 'Rivets' , 1000)
INSERT CarParts VALUES(1 , 'Door' , 'Rivets' , 100)
INSERT CarParts VALUES(1 , 'Door' , 'Mirror' , 1)

ÀÚµ¿Â÷ÀÇ ºÎÇ° ¹× ÇÏÀ§ ºÎÇ°¿¡ ´ëÇÑ Á¤º¸¸¦ °¡Áö°í ÀÖ´Â Å×À̺íÀ» ¸¸µé±â À§ÇÑ Äõ¸® ÀÔ´Ï´Ù. º¸Åë ÀÌ·¯ÇÑ Á¤º¸¸¦ ´ã°í ÀÖ´Â Å×À̺íÀ» 
Àç·áÇ¥(bill of materials)¶ó°í ºÎ¸¨´Ï´Ù. Àç±ÍÀû CTE ´Â Àç·áÇ¥ , Á¶Á÷µµ ¹× ±âŸ °èÃþÀûÀÎ ±¸Á¶¸¦ °®´Â µ¥ÀÌÅ͸¦ ¹ÝȯÇÏ´Â ÀÛ¾÷À» 
½±°Ô ÇÒ ¼ö ÀÖµµ·Ï ÇÕ´Ï´Ù. 

Áö±Ý »ý¼ºÇÏ´Â Å×À̺í Á¤º¸¿¡¼­ Body ¿Í °°Àº ºÎÇ°ÀÌ ¿©·¯ ÇÏÀ§ ºÎÇ°µéÀ» °¡Áö°í ÀÖ´Ù´Â »ç½ÇÀ» ÁÖ¸ñÇϽʽÿÀ.. 
¿¹¸¦ µé¾î, Body ºÎÇ°Àº 1000 °³ÀÇ ¸ø(rivet) À» ÇÏÀ§ ºÎÇ°À¸·Î °¡Áö°í ÀÖ°í, Body ÀÇ ÇÏÀ§ ºÎÇ°ÀÎ Door ¶ÇÇÑ ÀÚ½Å(Door) ÀÇ ÇÏÀ§ ºÎÇ°À¸·Î 
100°³ÀÇ ¸ø(rivet)À» °¡Áö°í ÀÖ½À´Ï´Ù.

WITH CarPartsCTE(SubPart , Qty)
AS 
(
    -- ¾ÞÄ¿¸â¹ö(Anchor Member): 
    -- CarPartsCTE ÀÚ½ÅÀ»ÂüÁ¶ÇÏÁö¾Ê´ÂSELECT Äõ¸®
    SELECT SubPart , Qty
        FROM CarParts
            WHERE Part = 'Body'
    UNION ALL
    -- Àç±Í¸â¹ö(Recursive Member):
    -- CTE(CarPartsCTE) ÀÚ±âÀÚ½ÅÀ»ÂüÁ¶ÇÏ´ÂSELECT Äõ¸®
    SELECT CarParts.SubPart    , CarPartsCTE.Qty * CarParts.Qty
        FROM CarPartsCTE INNER JOIN CarParts
            ON CarPartsCTE.SubPart = CarParts.Part
            WHERE CarParts.CarID = 1
)

-- Ãâ·ÂÄõ¸®
SELECT SubPart , SUM(Qty) as q FROM CarPartsCTE GROUP BY SubPart

Àç±ÍÀû CTE ´Â ÃÖ¼ÒÇÑ 2°³ ÀÌ»óÀÇ Äõ¸®µé·Î ±¸¼º µÇ¾îÁý´Ï´Ù. ù¹ø° ¿ä¼Ò·Î ±¸¼ºµÈ Äõ¸®´Â CTE ÀÚü¸¦ ÂüÁ¶ÇÏÁö ¾Ê´Â Äõ¸®ÀÔ´Ï´Ù.
ÀÌ·¯ÇÑ Äõ¸® Á¤ÀÇ´Â CTE ±¸Á¶ÀÇ ±âº» °á°ú ÁýÇÕÀ» Çü¼ºÇϱ⠶§¹®¿¡ ¾ÞÄ¿ ¸â¹ö(anchor member)¶ó°í ÇÕ´Ï´Ù. µÎ ¹ø° ±¸¼º¿ä¼Ò´Â Àç±Í 
¸â¹ö(recursive member) ¶ó°í ºÒ¸®¿öÁö´Â Àç±Í Äõ¸®ÀÔ´Ï´Ù. ÀÌ·¯ÇÑ Äõ¸®µéÀº UNION ALL ¿¬»êÀÚ¿¡ ÀÇÇØ ±¸º°µÇ¾î Áý´Ï´Ù.

ÀÚµ¿Â÷ÀÇ º»Ã¼(Body) ¸¦  ¸¸µé±â À§ÇØ ÇÊ¿äÇÑ ºÎÇ°µéÀÇ ÃÑ ¼ö·®¿¡ ´ëÇÑ ¸®½ºÆ®¸¦ ¾ò¾î¿À´Â Äõ¸® ÀÔ´Ï´Ù.  
°øÅë Å×ÀÌºí ½Ä(CTE)Àº ¸Ç óÀ½  °£´ÜÇÑ Äõ¸®(“SELECT SubPart, Qty FROM CarParts WHERE Part = 'Body'”.)·ÎºÎÅÍ ±âº» °á°ú ÁýÇÕÀ» ¸¸µì´Ï´Ù. 
±× ´ÙÀ½,  ÀÌ ºÎÇ°µéÀÇ ÇÏÀ§ ºÎÇ°µé°ú  ÀÌ ÇÏÀ§ ºÎÇ°ÀÇ °³¼ö(ÇÊ¿äÇÑ »óÀ§ ºÎÇ°ÀÇ °³¼ö *  »óÀ§ ºÎÇ° ´ÜÀ§´ç ÇÊ¿äÇÑ ÇÏÀ§ ºÎÇ° °³¼ö)
¿¡ ´ëÇÑ Á¤º¸¸¦ ¾ò¾î¿À´Â Äõ¸®¹®À» UNION ALL ¿¬»êÀÚ·Î °áÇÕÇÕ´Ï´Ù. µÎ ¹ø° Äõ¸®¹®ÀÇ INNER JOIN ¹®Àå ¾È¿¡ CarPartsCTE ¶ó´Â À̸§À» °¡Áø 
°øÅë Å×ÀÌºí ½Ä(CTE) ÀÚü¿¡ ´ëÇÑ ÂüÁ¶ (Àç±Í ÂüÁ¶)  ¸¦ Æ÷ÇÔÇÏ´Â °ÍÀÔ´Ï´Ù.


Àç±Í Äõ¸®¸¦ ÀÌ¿ëÇÑ 1~ 10±îÁö Äõ¸®

WITH TEST AS(
    SELECT IDX = 1 UNION ALL
    SELECT IDX = IDX + 1 FROM TEST WHERE IDX < 10
)SELECT * FROM TEST

4. ÇÁ·Î½ÃÁ®¿Í CTE¸¦ ÀÌ¿ëÇÑ Æ®¸®±¸Á¶ ¸¸µå´Â ¿¹Á¦...

 CREATE PROCEDURE TREE_CALL (@url1 varchar(100)) as
BEGIN 
    ;
    with cte (board_idx,m_name, m_step, m_sex, m_homepage,url_name,m_writeday, m_level , path1)
    as
    (
        select board_idx,m_name, m_step, left(m_jumin2,1) as m_sex, m_homepage,url_name, m_writeday, 1 as m_level,
            convert(varchar(1000), ' > ' + m_homepage) path1 
            from demo005_member where (m_homepage is not null) and (m_homepage<>'') and (m_homepage=@url1)
        union all
        select A.board_idx, A.m_name, A.m_step, left(A.m_jumin2,1) as m_sex, A.m_homepage, A.url_name , A.m_writeday, m_level+1 , 
            convert(varchar(1000), path1 + ' > ' + A.m_homepage)
            from demo005_member A, cte B where a.url_name = b.m_homepage and (A.m_homepage is not null) and (A.m_homepage<>'')
    )
    select board_idx, m_name, m_step, m_sex, m_homepage, url_name , m_writeday, m_level , path1 from cte  order by path1 asc
end
¡Ø Ȥ½Ã µµ¿òÀÌ µÇ¼Ì´Ù¸é ´ñ±Û¿¡ ÇѸ¶µð ³²°ÜÁÖ¼¼¿ä!
ÀÛ¼ºÀÚ   ºñ¹Ð¹øÈ£
ÀÚµ¿±Û ¹æÁö     (ÀÚµ¿±Û ¹æÁö ±â´ÉÀÔ´Ï´Ù.)
³»¿ë   ´ñ±Û´Þ±â 
À̸ÞÀÏ ¹®ÀÇ : cak0280@nate.com  
Copyright 2000 By ENTERSOFT.KR All Rights Reserved.