MS-SQL > À¯¿ëÇÑ Äõ¸® ¸ðÀ½. µî·ÏÀÏ : 2017-07-03 19:02 Á¶È¸¼ö : 53,008ÁýÇÕ(SET) : sqlÀº ºÐ¸í ÁýÇÕÀ» ÀÌ¿ëÇÑ´Ù. Ä¿¼»ç¿ëÀ» ÀÚÁ¦ÇÏÀÚ.
±³ÁýÇÕ, Â÷ÁýÇÕ, ÇÕÁýÇÕ - ¿¹Àü¿¡ ÃʵîÇлý ¾Æ´Ô ÁßÇлý ½ÃÀý Áö°ã°Ô(?) µè´ø ´Ü¾îµéÀÌÁö¿ä /*==========================================================*/ ¸ÕÀú »ùÇÃÀ» ¸¸µé¾îµÎ°í --drop table #a --drop table #b create table #a(id int) create table #b(id int) go insert into #a values(1) insert into #a values(2) insert into #a values(3) insert into #a values(4) insert into #a values(5) insert into #a values(6) insert into #a values(7) insert into #a values(8) insert into #b values(2) insert into #b values(4) insert into #b values(6) insert into #b values(8) go ÀÌÁ¦, ¾ÆÁÖ °£´ÜÈ÷ º¸µµ·Ï ÇÏÁö¿ä /*==========================================================*/ 1. ±³ÁýÇÕ (intersect) ¾Æ½±Áö¸¸ ÀÌ·±ÇÔ¼ö´Â sql¿¡ ¾ø½À´Ï´Ù. (Analysis Services¿ëÀ¸·Î´Â ÀÖÁö¸¸ t-sqlÇÔ¼ö´Â ¾Æ´ÏÁö¿ä) ±×·³ ÀÌ·±°æ¿ì´Â ¾î¶»°Ô ÇÒ±î¿ä ? -> in À̳ª exists ¸¦ ÀÌ¿ëÇϴ°̴ϴÙ. ¶Ç´Â Á¶ÀÎÀ» »ç¿ëÇÏÁö¿ä. /*==========================================================*/ ¿¹Á¦ : Å×À̺í1 °ú Å×À̺í2 µÑ´Ù µé¾îÀִ°ÍÀº ? 1. in »ç¿ë select * from #a where id in (select id from #b) 2. exists »ç¿ë select * from #a x where exists(select * from #b y where y.id=x.id) 3. Á¶Àλç¿ë select x.* from #a x inner join #b y on (y.id = x.id) /*==========================================================*/ 2. Â÷ÁýÇÕ (except, minus) ¾Æ½±Áö¸¸ ÀÌ·±ÇÔ¼ö´Â sql¿¡ ¾ø½À´Ï´Ù. (Analysis Services¿ëÀ¸·Î´Â ÀÖÁö¸¸ t-sqlÇÔ¼ö´Â ¾Æ´ÏÁö¿ä) ±×·³ ÀÌ·±°æ¿ì´Â ¾î¶»°Ô ÇÒ±î¿ä ? -> not in À̳ª not exists ¸¦ ÀÌ¿ëÇϴ°̴ϴÙ. ¶Ç´Â outer joinÀ» »ç¿ëÇϴ°ÍÀÔ´Ï´Ù. /*==========================================================*/ ¿¹Á¦2 : Å×À̺í1 ¿¡´Â Àִµ¥ Å×À̺í 2¿¡´Â ¾ø´Â °ÍÀº ? 1. not in »ç¿ë select * from #a where id not in (select id from #b) 2. not exists »ç¿ë select * from #a x where not exists(select * from #b y where y.id=x.id) 3. outer join »ç¿ë select x.* from #a x left outer join #b y on (x.id = y.id) where y.id is null /*==========================================================*/ 3. ÇÕÁýÇÕ (union) À¯ÀÏÇÏ°Ô Áö¿øµÇ´Â ÇÔ¼öÀÔ´Ï´Ù. /*==========================================================*/ ¿¹Á¦ : Å×À̺í1 ¿¡ Àִ°Ͱú Å×À̺í 2¿¡ Àִ°ÍÀ» ¸ðµÎ±¸ÇÒ¶§´Â ? 1. union »ç¿ë : Áߺ¹Á¦°Å¸¦ À§ÇØ sort¸¦ ÇÑ´Ù. select * from #a union select * from #b |--Sort(DISTINCT ORDER BY:([Union1004] ASC)) --> Áߺ¹Á¦°Å¸¦ À§Çؼ sort¸¦ ÇÑ´Ù. |--Concatenation |--Table Scan(OBJECT:([tempdb].[dbo].[#a])) |--Table Scan(OBJECT:([tempdb].[dbo].[#b])) 2. union all »ç¿ë : Áߺ¹Çã¿ë select * from #a union all select * from #b |--Concatenation --> sort°¡ ¾ø´Ù. |--Table Scan(OBJECT:([tempdb].[dbo].[#a])) |--Table Scan(OBJECT:([tempdb].[dbo].[#b)) /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ ¿©±â±îÁö °£´ÜÇÏ°Ô ÁýÇÕÀÇ °³³äÀ» ºÃ°í ÀÌÁ¦ in °ú union ¿¡ ´ëÇÏ¿© Á¶±Ý¸¸ ´õ »ìÆ캸µµ·Ï ÇÏÁö¿ä. /*==========================================================*/ 1. in : ÁÖ¾îÁø °ªÀÌ ÇÏÀ§ Äõ¸® ¶Ç´Â ¸ñ·Ï¿¡ ÀÖ´Â ÀÓÀÇÀÇ °ª°ú ÀÏÄ¡ÇÏ´ÂÁö È®ÀÎÇÕ´Ï´Ù. ±¸¹® test_expression [ NOT ] IN ( subquery | expression [ ,...n ] ) ex) ȸ¿øÅ×À̺í(¾ÆÀ̵ð, À̸§, ·¹º§) 1 È«±æµ¿ 1 2 ¯±¸ 1 3 »×»×ÀÌ 2 --drop table ȸ¿ø create table ȸ¿ø (¾ÆÀ̵ð int, À̸§ varchar(10), ·¹º§ int) create index idx on ȸ¿ø(·¹º§) go insert into ȸ¿ø values(1, "È«±æµ¿", 1) insert into ȸ¿ø values(2, "¯±¸", 1) insert into ȸ¿ø values(3, "»×»×ÀÌ", 2) go select * from ȸ¿ø where ·¹º§ in (1, 2) |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([pubs].[dbo].[ȸ¿ø])) |--Index Seek(OBJECT:([pubs].[dbo].[ȸ¿ø].[idx]), SEEK:([ȸ¿ø].[·¹º§]=1 OR [ȸ¿ø].[·¹º§]=2) ORDERED FORWARD) ½ÇÇó°èȹÀ» º¸¸é ·¹º§ in (1, 2) ±¸¹®ÀÌ ·¹º§=1 OR ·¹º§=2 ¿Í °°ÀÌ or¿¬»êÀ¸·Î º¯°æ µÇ¾ú´Ù. ÀϹÝÀûÀ¸·Î ÀÌ·¯ÇÑ in ÀÇ °æ¿ì or ¿¬»êÀ¸·Î º¯°æµÇ¾î ½ÇÇàµÈ´Ù. ±×·³, Á»´Ù¸¥ ¹æ¹ýÀ¸·Î declare @lev1 int, @lev2 int set @lev1 = 1 set @lev2 = 2 select * from ȸ¿ø where ·¹º§ in (@lev1, @lev2) |--Table Scan(OBJECT:([pubs].[dbo].[ȸ¿ø]), WHERE:(([ȸ¿ø].[·¹º§]=[@lev2]) OR [ȸ¿ø].[·¹º§]=[@lev1])) ¿¹»óÇß´ø index seek ¹æ½ÄÀÌ ¾Æ´Ï¶ó table scan ¹æ½ÄÀÌ´Ù. sql-server °¡ Cost base ¹æ½ÄÀÇ ¿ÉƼ¸¶ÀÌÁ®¸¦ »ç¿ëÇÏ´Ùº¸´Ï ÀÌ·±°á°ú°¡ ³ª¿Â´Ù. Áï, À§ °æ¿ì¿¡ @lev1¸¸À» °¡Áö°í Äõ¸®¸¦ ÇÑ´Ù¸é index seek ¹æ½ÄÀ¸·Î 󸮵ȴÙ. ÇÏÁö¸¸ À§ °á°ú¸¦ º¸¸é ´ÜÁö 2°³ÀÇ º¯¼ö¸¦ Àû¿ëÇÏÀÚ table scanÂÊÀ¸·Î µ¹¾Æ¼±´Ù. ¿Ö ±×·²±î ? ÀϹÝÀûÀ¸·Î sql-server´Â »ó¼ö°ªÀÌ Äõ¸®¿¡¼ »ç¿ëµÇ¸é Á¤È®ÇÑ Åë°èÁ¤º¸¸¦ »ç¿ëÇÏ¿© index¸¦ »ç¿ëÇÒÁö table scanÀ¸·Î °¥Áö °áÁ¤À» ÇÏÁö¸¸ ¾Ë¼ö¾ø´Â º¯¼ö°ªÀÌ µé¾î¿À¸é ±×³É Æò±Õ°ªÀ» »ç¿ëÇÑ´Ù°í ÇÑ´Ù. ±×·¡¼ ÀÌ°æ¿ì sql-server°¡ table scanÀ» ¼±ÅÃÇÑ°ÍÀÌ´Ù. ÀÌ·±°æ¿ì¿¡ ÈùÆ®¸¦ »ç¿ëÇØ¾ß Á¤»óÀûÀÎ index È°¿ëÀ» ÇÑ´Ù. ¹°·Ð, ¿¹Á¦°¡ ¾ûÅ͸® ÀÌÁö¸¸ ½Ç¹«¿¡¼µµ Çѹø Å×½ºÆ® Çغ¸±â ¹Ù¶õ´Ù. ¿©±â ¿¹Á¦¿Í ´Ù¸£Áö ¾ÊÀ»°ÍÀÌ´Ù. Çϳª´õ, ÀϹÝÀûÀ¸·Î sql-server´Â ¾Õ¿¡¼ ºÎÅÍ ÆĽÌÀ» ÇÏÁö¸¸ º¯¼ö¸¦ »ç¿ëÇÑ in ÀÇ °æ¿ì´Â ¹Ý´ë·Î µÚ¿¡¼ºÎÅÍ ÆĽÌÀ» ÇÑ´Ù. À̰͵µ ¾Ë¾ÆµÑ ÇÊ¿ä´Â ÀÖÀ»µí. ±×·¸´Ù°íÇؼ in¾È¿¡ ³ª¿µÈ¼ø¼ ¶Ç´Â ¿ª¼øÀ¸·Î Á¤·ÄÀ̵Ǵ°ÍÀº Àý´ë ¾Æ´Ï´Ù. Á¤·ÄµÈ ¼ø¼¸¦ ¿øÇÑ´Ù¸é ¹Ýµå½Ã ¸í½ÃÀûÀ¸·Î order by ¸¦ ½á¼ Á¤·Ä¼ø¼¸¦ ÁöÁ¤ÇØÁÖ¾î¾ßÇÑ´Ù. declare @lev1 int, @lev2 int set @lev1 = 1 set @lev2 = null select * from ȸ¿ø where ·¹º§ in (@lev1, @lev2) ÀÌ°æ¿ì´Â ¾î¶»°Ô µÉ±î ? -> declare @lev1 int, @lev2 int set @lev1 = null set @lev2 = null select * from ȸ¿ø where ·¹º§ in (@lev1, @lev2) ¶Ç, ÀÌ·± °æ¿ì´Â ¾î¶»°Ô µÉ±î ? °¢ÀÚ Çغ¸½Ã±æ... /*-----------------------------------------------------------------------*/ 1-1. in-subquary 1. in-subquaryÀÇ °æ¿ì join¹®À¸·Î Çؼ®ÀÌ µÈ´Ù. 2. in-subquary°¡ ¸ÕÀú ÀÐÈú¼öµµ, ³ªÁß¿¡ ÀÐÈú¼öµµ ÀÖ´Ù -> À妽º À¯¹«, Äõ¸®À¯Çü µî¿¡ µû¶ó¼ ´Þ¶óÁø´Ù. 3. °í¼ö°¡ ¾Æ´Ï¶ó¸é in-subquary ½ÇÇà½Ã ¹Ýµå½Ã ½ÇÇà°èȹÀ» È®ÀÎÇغ¸½Ã±æ ±ÇÀåÇÕ´Ï´Ù. °¡²û À̳ðÀÌ »ý°¢Çѵ¥·Î ÀÛµ¿À» ¾ÈÇϴ¼ö°¡ ÀÖÀ¸´Ï Á¶½É... /*-----------------------------------------------------------------------*/ »óÇ°Å×À̺í(»óÇ°ÄÚµå, »óÇ°¸í, ºÐ·ùÄÚµå) ºÐ·ùÅ×À̺í(ºÐ·ùÄÚµå, Ä«Å×°í¸®¸í, µî±Þ) ÀÌ·±½ÄÀ¸·Î µÇ¾î ÀÖÀ»°æ¿ì »óÇ°Å×ÀÌºí¿¡¼ Ä«Å×°í¸®µî±ÞÀÌ "A"Àΰ͵éÀÇ ¸ñ·ÏÀ» º¸°í½Í´Ù¸é select * from »óÇ° where ºÐ·ùÄÚµå in (select ºÐ·ùÄÚµå from ºÐ·ù where µî±Þ = "A") ÀÌ·¸°Ô Äõ¸®¸¦ ÇÏ¸é ¿ÉƼ¸¶ÀÌÀú°¡ select »óÇ°.* from »óÇ° inner join ºÐ·ù on »óÇ°.ºÐ·ùÄÚµå = ºÐ·ù.ºÐ·ùÄÚµå and ºÐ·ù.µî±Þ = "A" ÀÌ·±½ÄÀ¸·Î inner joinÀ¸·Î Ç®¾î¼ 󸮸¦ ÇÑ´Ù. ÀÌ·±½ÄÀÇ Äõ¸®¹®Àº ´ëºÎºÐÀÇ °æ¿ì in-subquary°¡ ¸ÕÀú ½ÇÇàµÇ´Â Á¶Àι®À¸·Î Çؼ®ÀÌ µÇ¾î ½ÇÇà°èȹÀÌ ³ª¿Ã°ÍÀ¸·Î ±â´ëÇÏÁö¸¸ ±×·¸Áö ¾ÊÀº °æ¿ìµµ ÀÖ´Ù. in-subquaryÀÇ °æ¿ì ÀϹÝÀûÀ¸·Î in-subquary°¡ ¸ÕÀú ÀÐÇô¼ main quary°¡ ³ªÁß¿¡ 󸮵DZ⸦ ±â´ëÇÏ°í Äõ¸®¹®À» ÀÛ¼ºÇÏ°Ô µÈ´Ù. ÀϹÝÀûÀ¸·Î ÀÌ·¸°Ô Ç®¸®Áö¸¸ °æ¿ì¿¡ µû¶ó¼´Â ±×·¸Áö ¾Ê°í main quary°¡ ¸ÕÀú ÀÐÈ÷¸é¼ in-subquary¸¦ ³ªÁß¿¡ filterÁ¶°ÇÀ¸·Î ó¸®Çϴ°æ¿ì°¡ Á¾Á¾ ¹ß»ýÇÑ´Ù. ·¹Äڵ尡 ¸¹Áö ¾ÊÀº°æ¿ì¿¡´Â Å©°Ô ¼º´É»ó ¹®Á¦°¡ µÇÁö ¾Ê°ÚÁö¸¸ ±×·¸Áö ¾ÊÀº °æ¿ì´Â ½É°¢ÇÑ ¼º´É»óÀÇ ÀúÇϸ¦ °¡Á®¿Â´Ù. ÀÌ°ÍÀ» ÁÖÀÇÇØ¾ß Çϴ°ÍÀÌ´Ù. ±×·¡¼, °³¹ßÀÚµéÀº º»ÀÎÀÌ °í¼ö°¡ ¾Æ´Ï¶ó¸é ½ÇÇà°èȹÀ» È®ÀÎÇÏ¿©¾ß ÇÑ´Ù´Â °ÍÀÌ´Ù. À§ ¿¹Á¦ÀÇ °æ¿ì¸¦ °¡Áö°í »ìÆ캻´Ù¸é in-subquary°¡ ¸ÕÀú ó¸®µÈ´Ù¸é ºÐ·ù Å×ÀÌºí¿¡¼ µî±ÞÀÌ "A"ÀÎ ºÐ·ùÄÚµåµé¸¸À» ¸ÕÀú ÀÐ¾î¼ ±×°ÍÀ» °¡Áö°í »óÇ°Å×À̺íÀÇ ºÐ·ùÄÚµå À妽º¸¦ »ç¿ëÇÑ´Ù¸é ÃÖÀûÀÏ°ÍÀÌ´Ù. main-quary°¡ ¸ÕÀú ó¸®µÈ´Ù¸é »óÇ°Å×À̺íÀ» ¹«Á¶°Ç Ç®·Î ÀÐ¾î¼ ¶Ç´Â ºÐ·ùÄÚµå À妽º¸¦ Ç®·Î ÀÐÀ¸¸é¼ °¢ row¸¶´Ù ºÐ·ù Å×ÀÌºí¿¡¼ ÇØ´çºÐ·ùÄڵ尡 µî±ÞÀÌ "A"ÀÎÁö üũÇÏ¿© °É·¯ÁÖ´Â ÇüÅ·Π󸮵ȴÙ. ÀÌ·±°æ¿ì ÀϹÝÀûÀ¸·Î Äõ¸®¼º´ÉÀÌ ¶³¾îÁö°Ô µÇ´Â°ÍÀÌ´Ù. ±×·¯¸é Á¶Àι®À» »ç¿ëÇÏÁö ¿Ö ±»ÀÌ in-subquary¸¦ »ç¿ëÇß´À³Ä ? À§ »ùÇÃÀÌ ±×´ÙÁö ÁÁÀº »ùÇÃÀÌ ¾Æ´Ï¶ó ±×·±°ÍÀÌ°í ¾Æ·¡ »ùÇÃÀ» º¸ÀÚ. use tempdb go set statistics profile off set statistics io off --¿¹Á¦1. Å×½ºÆ®¸¦ À§ÇÑ »ùÇà ÀÛ¼º --drop table ÄÚµå create table ÄÚµå(»óÇ°ÄÚµå int not null, »óÇ°¸í varchar(40)) go alter table ÄÚµå add constraint pk_ÄÚµå primary key(»óÇ°ÄÚµå) go set nocount on declare @i int set @i = 1 while (@i <= 50) begin insert into ÄÚµå values(@i, convert(varchar(10), @i) ) set @i = @i + 1 end set nocount off go select count(*) from ÄÚµå --50 --drop table ¸ÅÃ⸶°¨ create table ¸ÅÃ⸶°¨(»óÇ°ÄÚµå int not null, ¸ÅÃâÀÏÀÚ char(8) not null, ¼ö·® int) go alter table ¸ÅÃ⸶°¨ add constraint pk_¸ÅÃ⸶°¨ primary key (»óÇ°ÄÚµå, ¸ÅÃâÀÏÀÚ) go set nocount on declare @i int, @j int declare @dt datetime set @i = 1 set @dt = "2000-01-01" while (@dt < "2004-01-01") --4³âÄ¡ »ùÇÃÀÚ·á ¸¸µé±¸ begin set @j = 1 while (@j <= 50) begin insert into ¸ÅÃ⸶°¨ values(@j, convert(varchar(8), @dt, 112), convert(int, rand() * 1000) ) set @j = @j + 1 end set @dt = dateadd(dd, 1, @dt) end set nocount off go select count(*) from ¸ÅÃ⸶°¨ --73050 set statistics profile on set statistics io on --¹®Á¦ : 2003 ³â 5¿ù ¸¶°¨³»¿ª list ? 1. ÀϹÝÀûÀ¸·Î ±×³É ¾Æ¹«»ý°¢¾øÀÌ Äõ¸®¸¦ ÇÑ´Ù¸é select * from ¸ÅÃ⸶°¨ where ¸ÅÃâÀÏÀÚ between "20030501" and "20030531" |--Clustered Index Scan(OBJECT:([T1].[dbo].[¸ÅÃ⸶°¨].[pk_¸ÅÃ⸶°¨]), WHERE:([¸ÅÃ⸶°¨].[¸ÅÃâÀÏÀÚ]>=[@1] AND [¸ÅÃ⸶°¨].[¸ÅÃâÀÏÀÚ]<=[@2])) "¸ÅÃ⸶°¨" Å×À̺í. ½ºÄµ ¼ö 1, ³í¸®Àû Àб⠼ö 299, ¹°¸®Àû Àб⠼ö 0, ¹Ì¸® Àб⠼ö 0. index seekÀÌ ¾Æ´Ï¶ó index scan¹æ½ÄÀ¸·Î ½ÇÇó°èȹÀÌ Ç®·È´Ù. À妽º¸¦ È°¿ëÀ» ¸øÇÑ´Ù. ù¹ø° Ä÷³À» »ç¿ëÇÏÁö ¸øÇϱ⠶§¹®ÀÌ´Ù. 2. ù¹ø° Ä÷³À» in-subquary¸¦ »ç¿ëÇÏ¿© ÀÎÀ§ÀûÀ¸·Î °ø±ÞÇÔÀ¸·Î½á Á¤»óÀûÀ¸·Î À妽º¸¦ È°¿ëÇÏ°Ô²û ÇÑ´Ù. select * from ¸ÅÃ⸶°¨ where »óÇ°ÄÚµå in (select »óÇ°ÄÚµå from ÄÚµå) and ¸ÅÃâÀÏÀÚ between "20030501" and "20030531" |--Nested Loops(Inner Join, OUTER REFERENCES:([ÄÚµå].[»óÇ°ÄÚµå]) WITH PREFETCH) |--Clustered Index Scan(OBJECT:([T1].[dbo].[ÄÚµå].[pk_ÄÚµå])) |--Clustered Index Seek(OBJECT:([T1].[dbo].[¸ÅÃ⸶°¨].[pk_¸ÅÃ⸶°¨]), SEEK:([¸ÅÃ⸶°¨].[»óÇ°ÄÚµå]=[ÄÚµå].[»óÇ°ÄÚµå] AND [¸ÅÃ⸶°¨].[¸ÅÃâÀÏÀÚ] >= "20030501" AND [¸ÅÃ⸶°¨].[¸ÅÃâÀÏÀÚ] <= "20030531") ORDERED FORWARD) "¸ÅÃ⸶°¨" Å×À̺í. ½ºÄµ ¼ö 50, ³í¸®Àû Àб⠼ö 112, ¹°¸®Àû Àб⠼ö 0, ¹Ì¸® Àб⠼ö 0. "ÄÚµå" Å×À̺í. ½ºÄµ ¼ö 1, ³í¸®Àû Àб⠼ö 2, ¹°¸®Àû Àб⠼ö 0, ¹Ì¸® Àб⠼ö 0. Á¤»óÀûÀ¸·Î À妽º¸¦ Àß È°¿ëÇÏ¿´°í Äõ¸®¼º´É¶ÇÇÑ ÈξÀ ¶Ù¾î³ª´Ù. ±×·¯³ª, ÀÌ°ÍÀº Å×½ºÆ®¸¦ À§ÇÏ¿© ÀÎÀ§ÀûÀ¸·Î ±×·¸°Ô ÇÑ°ÍÀÌ°í ½Ç¹«¿¡¼´Â ´Ù¾çÇÑ »óȲÀ» °ËÅäÇÏ¿© »ç¿ë¿©ºÎ¸¦ ÆÇ´ÜÇؾßÇÑ´Ù. Á¤¸» sqlÀº ¾î·Æ´Ù. ÀÌ¿¹Á¦ÀÇ °æ¿ìµµ »ùÇÃÀ» ¸¸µé¶§ 4³âÄ¡¸¦ ¸¸µéÁö ¾Ê°í 1³âÄ¡¸¸ ¸¸µé¾î¼ Å×½ºÆ®¸¦ Çغ¸¸é 1¹ø °æ¿ìó·³ ±×³É clustered index scan À» Çϴ°ÍÀÌ ÈξÀ È¿À²ÀÌ ´õ ÁÁ´Ù. ÀÌ¿¹Á¦¸¦ º¸¸é óÀ½ 2³âÁ¤µµ´Â ±×³É Äõ¸®ÇÏ¿© clustered index scan À» À¯µµÇÏ°í ÀÌÈÄ µ¥ÀÌÅÍ°¡ ´õ ¸¹ÀÌ ½×ÀÌ°Ô µÇ¸é in-subquary¸¦ È°¿ëÇÏ¿© clustered index seek À» À¯µµÇÏ´Â ¹æ½ÄÀ» »ç¿ëÇØ¾ß Äõ¸®È¿À²À» ÀÏÁ¤ÇÏ°Ô À¯ÁöÇÒ¼ö ÀÖ´Ù. ÀÌ·±°ÍÀÌ sqlÀÇ Àç¹Ì°¡ ¾Æ´Ò±î ? --¿¹Á¦2. : in-subquary¸¦ »ç¿ëÇÏ¿© À妽º¸¦ »ç¿ëÇÏ°Ô²û À¯µµÇÑ°ÍÀÌ ¿ÀÈ÷·Á È¿À²À» ¶³¾î¶ß¸®´Â °æ¿ì Å×½ºÆ®¸¦ À§ÇÑ »ùÇà ÀÛ¼º set statistics profile off set statistics io off --drop table t1 create table t1(dt char(8) not null, seq int not null, qty int, c1 char(100)) go alter table t1 add constraint pk_t1 primary key (dt, seq) go set nocount on declare @dt datetime declare @i int, @j int set @dt = "2000-01-01" while (@dt < "2004-01-01") begin set @i = convert(int, rand() * 100) set @j = 1 while (@j <= @i) begin insert into t1 values(convert(varchar(8),@dt,112),@j, convert(int,rand()*1000),convert(varchar(10),@j)) set @j = @j + 1 end set @dt = dateadd(dd, 1, @dt) end set nocount off select count(*) from t1 --74007 --drop table dumy_dt create table dumy_dt(dt char(8) not null, dt1 datetime) go alter table dumy_dt add constraint pk_dumy_dt primary key(dt) go set nocount on declare @dt datetime set @dt = "2000-01-01" while (@dt < "2004-01-01") begin insert into dumy_dt values( convert(varchar(8), @dt, 112), @dt ) set @dt = dateadd(dd, 1, @dt) end set nocount off --¹®Á¦ : 1¿ù ÀϺ° ÀÚ·áÁß seq °¡ 3 º¸´Ù ÀÛÀº list ? set statistics profile on set statistics io on select * from t1 where dt like "200301%" and seq < 3 |--Clustered Index Seek(OBJECT:([T1].[dbo].[t1].[pk_t1]), SEEK:([t1].[dt] >= "200301" AND [t1].[dt] < "200302"), WHERE:([t1].[seq]<3 AND like([t1].[dt], "200301%", NULL)) ORDERED FORWARD) "t1" Å×À̺í. ½ºÄµ ¼ö 1, ³í¸®Àû Àб⠼ö 25, ¹°¸®Àû Àб⠼ö 0, ¹Ì¸® Àб⠼ö 0. select * from t1 where dt like "200301%" and seq in (1, 2) |--Clustered Index Seek(OBJECT:([T1].[dbo].[t1].[pk_t1]), SEEK:([t1].[dt] >= "200301" AND [t1].[dt] < "200302"), WHERE:(like([t1].[dt], "200301%", NULL) AND ([t1].[seq]=2 OR [t1].[seq]=1)) ORDERED FORWARD) "t1" Å×À̺í. ½ºÄµ ¼ö 1, ³í¸®Àû Àб⠼ö 25, ¹°¸®Àû Àб⠼ö 0, ¹Ì¸® Àб⠼ö 0. select * from t1 where dt in (select dt from dumy_dt where dt like "200301%") and seq in (1, 2) |--Nested Loops(Inner Join, OUTER REFERENCES:([dumy_dt].[dt]) WITH PREFETCH) |--Clustered Index Seek(OBJECT:([T1].[dbo].[dumy_dt].[pk_dumy_dt]), SEEK:([dumy_dt].[dt] >= "200301" AND [dumy_dt].[dt] < "200302"), WHERE:(like([dumy_dt].[dt], "200301%", NULL)) ORDERED FORWARD) |--Clustered Index Seek(OBJECT:([T1].[dbo].[t1].[pk_t1]), SEEK:([t1].[dt]=[dumy_dt].[dt] AND [t1].[seq]=1 OR [t1].[dt]=[dumy_dt].[dt] AND [t1].[seq]=2) ORDERED FORWARD) "t1" Å×À̺í. ½ºÄµ ¼ö 62, ³í¸®Àû Àб⠼ö 207, ¹°¸®Àû Àб⠼ö 0, ¹Ì¸® Àб⠼ö 0. "dumy_dt" Å×À̺í. ½ºÄµ ¼ö 1, ³í¸®Àû Àб⠼ö 2, ¹°¸®Àû Àб⠼ö 0, ¹Ì¸® Àб⠼ö 0. À§ °á°ú¸¦ º¸¸é ÀÌ°æ¿ì´Â ¿ÀÈ÷·Á in-subquary¸¦ »ç¿ëÇÏ¿© index scan À» index seek ·Î À¯µµÇÑ°ÍÀÌ ¿ÀÈ÷·Á Äõ¸® È¿À²À» ¶³¾î¶ß¸®´Â °æ¿ìÀÌ´Ù. Áï, »óȲ¿¡ µû¶ó ÆÇ´ÜÇØ¾ß Çϴ°ÍÀÌ´Ù. ¸ðµç °æ¿ì¿¡ È¿À²ÀûÀÎ Äõ¸®¶õ º°·ç ¾ø´Ù. /*-----------------------------------------------------------------------*/ ¸¶Áö¸·À¸·Î Á¤¸®¸¦ Çغ¸ÀÚ. /*-----------------------------------------------------------------------*/ --¸ÕÀú »ùÇø¸µé±¸ set statistics profile off set statistics io off set nocount on go drop table ±Þ¿© drop table »ç¿ø drop table Á÷±Þ drop table ºÎ¼ go create table ºÎ¼ ( ºÎ¼ÄÚµå int not null primary key , ºÎ¼¸í varchar(40) , ºÎ¼±¸ºÐ int) go create index idx_ºÎ¼±¸ºÐ on ºÎ¼(ºÎ¼±¸ºÐ) create index idx_ºÎ¼¸í on ºÎ¼(ºÎ¼¸í) go insert into ºÎ¼ values (1, "°³¹ßºÎ", 2) insert into ºÎ¼ values (2, "¿µ¾÷ºÎ", 3) insert into ºÎ¼ values (3, "Ãѹ«ºÎ", 1) insert into ºÎ¼ values (4, "ÀÎÅͳݻç¾÷ºÎ", 2) insert into ºÎ¼ values (5, "Çϵå¿þ¾îºÎ", 2) go create table Á÷±Þ ( Á÷±ÞÄÚµå int not null primary key , Á÷±Þ¸í varchar(40)) go create index idx_Á÷±Þ¸í on Á÷±Þ(Á÷±Þ¸í) go insert into Á÷±Þ values(1, "»ç¿ø") insert into Á÷±Þ values(2, "´ë¸®") insert into Á÷±Þ values(3, "°úÀå") insert into Á÷±Þ values(4, "Â÷Àå") insert into Á÷±Þ values(5, "ºÎÀå") insert into Á÷±Þ values(6, "ÀÌ»ç") go create table »ç¿ø ( »ç¿ø¹øÈ£ int not null , À̸§ varchar(10) , ÀÔ»çÀÏÀÚ char(8) , Á÷±ÞÄÚµå int , ºÎ¼ÄÚµå int) go --À妽º Å×½ºÆ®¸¦ ¸ñÀûÀ¸·Î nonclustered ·Î Àâ¾ÒÀ½. alter table »ç¿ø add constraint pk_»ç¿ø primary key nonclustered(»ç¿ø¹øÈ£) create index idx_ºÎ¼ÄÚµå on »ç¿ø(ºÎ¼ÄÚµå) create index idx_Á÷±ÞÄÚµå on »ç¿ø(Á÷±ÞÄÚµå) create index idx_À̸§ on »ç¿ø(À̸§) create index idx_ÀÔ»çÀÏÀÚ on »ç¿ø(ÀÔ»çÀÏÀÚ) alter table »ç¿ø add constraint fk_ºÎ¼ foreign key(ºÎ¼ÄÚµå) references ºÎ¼(ºÎ¼ÄÚµå) alter table »ç¿ø add constraint fk_Á÷±Þ foreign key(Á÷±ÞÄÚµå) references Á÷±Þ(Á÷±ÞÄÚµå) go insert into »ç¿ø values (1, "¯±¸", "19990101", 1, 1) insert into »ç¿ø values (2, "¸Í±¸", "19990501", 1, 1) insert into »ç¿ø values (3, "»×»×ÀÌ", "20000101", 1, 1) insert into »ç¿ø values (4, "°³¶ËÀÌ", "20000101", 1, 3) insert into »ç¿ø values (5, "ŸÀÜ", "20000301", 2, 1) insert into »ç¿ø values (6, "ġŸ", "20000402", 2, 2) insert into »ç¿ø values (7, "³ÀåÀÌ", "20000405", 2, 1) insert into »ç¿ø values (8, "¹é¼³ÀÌ", "20001011", 3, 1) insert into »ç¿ø values (9, "ÀÀ»ïÀÌ", "20010304", 3, 4) insert into »ç¿ø values (10, "Ǫ", "20010404", 4, 5) insert into »ç¿ø values (11, "ƼĿ", "20010404", 4, 1) insert into »ç¿ø values (12, "»ÇºüÀÌ", "20021010", 5, 1) insert into »ç¿ø values (13, "¿Ã¸®¹ö", "20030101", 1, 5) go create table ±Þ¿© ( »ç¿ø¹øÈ£ int not null , ±Þ¿©³â¿ù char(6) not null , ±Þ¿© int) go alter table ±Þ¿© add constraint pk_±Þ¿© primary key(»ç¿ø¹øÈ£, ±Þ¿©³â¿ù) alter table ±Þ¿© add constraint fk_±Þ¿© foreign key(»ç¿ø¹øÈ£) references »ç¿ø(»ç¿ø¹øÈ£) go insert into ±Þ¿© values(1, "200212", 100) insert into ±Þ¿© values(2, "200212", 150) insert into ±Þ¿© values(3, "200212", 200) insert into ±Þ¿© values(1, "200301", 100) insert into ±Þ¿© values(2, "200301", 200) insert into ±Þ¿© values(3, "200301", 400) insert into ±Þ¿© values(4, "200301", 500) insert into ±Þ¿© values(5, "200301", 100) insert into ±Þ¿© values(6, "200301", 300) insert into ±Þ¿© values(7, "200301", 100) insert into ±Þ¿© values(8, "200301", 400) insert into ±Þ¿© values(9, "200301", 100) insert into ±Þ¿© values(10, "200301", 200) insert into ±Þ¿© values(11, "200301", 100) insert into ±Þ¿© values(12, "200301", 200) insert into ±Þ¿© values(13, "200301", 100) insert into ±Þ¿© values(1, "200302", 100) insert into ±Þ¿© values(2, "200302", 600) insert into ±Þ¿© values(3, "200302", 100) insert into ±Þ¿© values(4, "200302", 500) insert into ±Þ¿© values(5, "200302", 100) insert into ±Þ¿© values(6, "200302", 400) insert into ±Þ¿© values(7, "200302", 100) insert into ±Þ¿© values(8, "200302", 200) insert into ±Þ¿© values(9, "200302", 100) insert into ±Þ¿© values(10, "200302", 300) insert into ±Þ¿© values(11, "200302", 110) insert into ±Þ¿© values(12, "200302", 100) insert into ±Þ¿© values(13, "200302", 200) insert into ±Þ¿© values(1, "200303", 200) insert into ±Þ¿© values(2, "200303", 600) insert into ±Þ¿© values(3, "200303", 130) insert into ±Þ¿© values(4, "200303", 400) insert into ±Þ¿© values(5, "200303", 100) insert into ±Þ¿© values(6, "200303", 300) insert into ±Þ¿© values(7, "200303", 100) insert into ±Þ¿© values(8, "200303", 120) insert into ±Þ¿© values(9, "200303", 100) insert into ±Þ¿© values(10, "200303", 300) insert into ±Þ¿© values(11, "200303", 150) insert into ±Þ¿© values(12, "200303", 100) insert into ±Þ¿© values(13, "200303", 100) go set nocount off go set statistics profile on set statistics io on /*-----------------------------------------------------------------------*/ 1-1-1 in-subquary °¡ ¸ÕÀú ÀÐÈ÷´Â °æ¿ì(ÀϹÝÀûÀ¸·Î ¿øÇÏ´Â ÇüÅÂ) /*-----------------------------------------------------------------------*/ select * from »ç¿ø where ºÎ¼ÄÚµå in (select ºÎ¼ÄÚµå from ºÎ¼ where ºÎ¼±¸ºÐ = 1) |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([tempdb].[dbo].[»ç¿ø])) |--Nested Loops(Inner Join, OUTER REFERENCES:([ºÎ¼].[ºÎ¼ÄÚµå])) |--Index Seek(OBJECT:([tempdb].[dbo].[ºÎ¼].[idx_ºÎ¼±¸ºÐ]), SEEK:([ºÎ¼].[ºÎ¼±¸ºÐ]=1) ORDERED FORWARD) |--Index Seek(OBJECT:([tempdb].[dbo].[»ç¿ø].[idx_ºÎ¼ÄÚµå]), SEEK:([»ç¿ø].[ºÎ¼ÄÚµå]=[ºÎ¼].[ºÎ¼ÄÚµå]) ORDERED FORWARD) /*-----------------------------------------------------------------------*/ 1-1-2. in-subquary °¡ ³ªÁß¿¡ ÀÐÈ÷´Â °æ¿ì /*-----------------------------------------------------------------------*/ --create index idx_ºÎ¼ÄÚµå on »ç¿ø(ºÎ¼ÄÚµå) drop index »ç¿ø.idx_ºÎ¼ÄÚµå --Å×½ºÆ®¸¦ À§Çؼ °Á¦ÀûÀ¸·Î À妽º¸¦ Áö¿ì°í go select * from »ç¿ø where ºÎ¼ÄÚµå in (select ºÎ¼ÄÚµå from ºÎ¼ where ºÎ¼±¸ºÐ = 1) |--Nested Loops(Left Semi Join, OUTER REFERENCES:([»ç¿ø].[ºÎ¼ÄÚµå])) |--Table Scan(OBJECT:([tempdb].[dbo].[»ç¿ø])) |--Index Seek(OBJECT:([tempdb].[dbo].[ºÎ¼].[idx_ºÎ¼±¸ºÐ]), SEEK:([ºÎ¼].[ºÎ¼±¸ºÐ]=1 AND [ºÎ¼].[ºÎ¼ÄÚµå]=[»ç¿ø].[ºÎ¼ÄÚµå]) ORDERED FORWARD) select * from »ç¿ø where »ç¿ø¹øÈ£ in (select »ç¿ø¹øÈ£ from ±Þ¿© where ±Þ¿©³â¿ù like "2002%") |--Nested Loops(Left Semi Join, OUTER REFERENCES:([»ç¿ø].[»ç¿ø¹øÈ£])) |--Table Scan(OBJECT:([tempdb].[dbo].[»ç¿ø])) |--Clustered Index Seek(OBJECT:([tempdb].[dbo].[±Þ¿©].[pk_±Þ¿©]), SEEK:([±Þ¿©].[»ç¿ø¹øÈ£]=[»ç¿ø].[»ç¿ø¹øÈ£] AND [±Þ¿©].[±Þ¿©³â¿ù] >= "2002" AND [±Þ¿©].[±Þ¿©³â¿ù] < "2003"), WHERE:(like([±Þ¿©].[±Þ¿©³â¿ù], "2002%", NULL)) ORDERED FORWARD) À̹ø¿¡´Â in-subquary°¡ ³ªÁß¿¡ ÀÐÇû³×¿ä. Áï, ¿øÇϴ´ë·Î ÀÛµ¿À» ¾ÈÇÑ°ÍÀÌÁö¿ä. ÀÌ·±°æ¿ì´Â ¾öû³ ºñÈ¿À²À» °¡Á®¿É´Ï´Ù. À妽º¸¦ Çϳª¸¸µé±¸ create index idx_±Þ¿¬³â¿ù on ±Þ¿©(±Þ¿©³â¿ù) go select * from »ç¿ø where »ç¿ø¹øÈ£ in (select »ç¿ø¹øÈ£ from ±Þ¿© where ±Þ¿©³â¿ù like "2002%") |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([tempdb].[dbo].[»ç¿ø])) |--Nested Loops(Inner Join, OUTER REFERENCES:([±Þ¿©].[»ç¿ø¹øÈ£])) |--Sort(DISTINCT ORDER BY:([±Þ¿©].[»ç¿ø¹øÈ£] ASC)) | |--Index Seek(OBJECT:([tempdb].[dbo].[±Þ¿©].[idx_±Þ¿¬³â¿ù]), SEEK:([±Þ¿©].[±Þ¿©³â¿ù] >= "2002" AND [±Þ¿©].[±Þ¿©³â¿ù] < "2003"), WHERE:(like([±Þ¿©].[±Þ¿©³â¿ù], "2002%", NULL)) ORDERED FORWARD) |--Index Seek(OBJECT:([tempdb].[dbo].[»ç¿ø].[pk_»ç¿ø]), SEEK:([»ç¿ø].[»ç¿ø¹øÈ£]=[±Þ¿©].[»ç¿ø¹øÈ£]) ORDERED FORWARD) ÀÌÁ¦ Á¤»óÀûÀ¸·Î in-subquary°¡ ¸ÕÀú ÀÐÇûÁö¿ä. À妽º¶ó´Â °ÍÀÌ ÀÌ·¸°Ô ¾öû³ Â÷À̸¦ °¡Á®¿À´Â °ÍÀÔ´Ï´Ù. ±×·¸´Ù°í, ÀÌ·±½ÄÀ¸·Î À妽º¸¦ ¹«ÇÑÁ¤ ¸¸µé¼ö´Â ¾ø´Â°ÍÀÌÁö¿ä. ±×·¡¼, À妽º¸¦ ¸¸µå´Â°ÍÀ» Àü·«À̶ó°íµé ÇÕ´Ï´Ù. ±×¸¸Å ¸¹Àº °æ¿ìÀÇ ¼ö¸¦ µûÁ®º¸°í Äõ¸®À¯ÇüÀ» ¸é¹ÐÈ÷ ÆľÇÇÑ´ÙÀ½ ¸Ó¸®Ä«¶ôÀÌ ºüÁúÁ¤µµ·Î °í¹ÎÇغ¸°í ¸¸µé¾î¾ßÇϴ°ÍÀÌÁö¿ä. /*==========================================================*/ 2. union : µÎ °³ ÀÌ»óÀÇ Äõ¸® °á°ú¸¦ ¸ðµç Äõ¸®¿¡ ¼ÓÇÏ´Â ¸ðµç ÇàÀÇ ÇÕÀ¸·Î ±¸¼ºµÇ´Â ÇϳªÀÇ °á°ú ÁýÇÕÀ¸·Î °áÇÕÇÕ´Ï´Ù. ÀÌ°ÍÀº µÎ Å×À̺íÀÇ ¿À» °áÇÕÇÏ´Â Á¶ÀÎÀ» »ç¿ëÇÏ´Â °Í°ú´Â ´Ù¸¨´Ï´Ù. UNION ¿¬»êÀÚ¸¦ »ç¿ëÇÏ¿© µÎ °³ÀÇ Äõ¸® °á°ú ÁýÇÕÀ» °áÇÕÇÒ ¶§´Â ´ÙÀ½ µÎ °¡Áö ±âº» ±ÔÄ¢À» µû¶ó¾ß ÇÕ´Ï´Ù. ¿ÀÇ °³¼ö¿Í ¼ø¼°¡ ¸ðµç Äõ¸®¿¡¼ µ¿ÀÏÇØ¾ß ÇÕ´Ï´Ù. µ¥ÀÌÅÍ Çü½ÄÀÌ È£È¯µÇ¾î¾ß ÇÕ´Ï´Ù. ±¸¹® { < query specification > | ( < query expression > ) } UNION [ ALL ] < query specification | ( < query expression > ) [ UNION [ ALL ] < query specification | ( < query expression > ) [ ...n ] ] /*-----------------------------------------------------------------------*/ 2-1. »ç¿ëÇüÅ 1. ÇÕÁýÇÕ(À§¿¡¼ ºÃÀ¸¹Ç·Î »ý·«) - ¿Â¶óÀμ³¸í¼¿¡µµ ¼³¸íÀÌ ÀߵǾî ÀÖÀ¸´Ï Âü°í 2. Full Outer JoinÀÇ ´ë¾È 3. ½ÇÇà°èȹÀÇ ºÐ¸® /*-----------------------------------------------------------------------*/ 2-1-1. Full Outer JoinÀÇ ´ë¾È /*-----------------------------------------------------------------------*/ --drop table ¿¹±Ý³»¿ª create table ¿¹±Ý³»¿ª(ÅëÀå¹øÈ£ int, ÀϷùøÈ£ int, ¿¹±ÝÀÏÀÚ char(10), ¿¹±Ý¾× int) insert into ¿¹±Ý³»¿ª values (1, 1, "2003-06-01", 100) insert into ¿¹±Ý³»¿ª values (1, 2, "2003-06-03", 100) insert into ¿¹±Ý³»¿ª values (1, 3, "2003-06-05", 100) insert into ¿¹±Ý³»¿ª values (1, 4, "2003-06-07", 100) go --drop table Ãâ±Ý³»¿ª create table Ãâ±Ý³»¿ª(ÅëÀå¹øÈ£ int, ÀϷùøÈ£ int, Ãâ±ÝÀÏÀÚ char(10), Ãâ±Ý¾× int) insert into Ãâ±Ý³»¿ª values (1, 1, "2003-06-01", 50) insert into Ãâ±Ý³»¿ª values (1, 2, "2003-06-02", 50) insert into Ãâ±Ý³»¿ª values (1, 3, "2003-06-05", 50) ¹®Á¦ : À§¿Í °°ÀÌ Å×À̺íÀÌ ¼³°èµÇ¾î ÀÖ´Ù°í ÇÏÀÚ. ¹°·Ð ÀԱݳ»¿ª°ú Ãâ±Ý³»¿ªÀº ¾÷¹«ÀûÀ¸·Î ÇϳªÀÇ Å×À̺í·Î ¼³°è¸¦ Çß¾î¾ß ÇßÁö¸¸, ÀÌ¹Ì Àú·¸°Ô ¼³°èµÈ´ë·Î ¸î³âÀ» »ç¿ëÇØ¿Ô°í, ¼³°èº¯°æÀÌ ÈûÀÌ µé´Ù´Â °¡Á¤ÇÏ¿¡¼ ÀÏÀÚº° ÀÔÃâ±Ý³»¿ªÀ» º¸ÀÚ 1. Full Outer Join»ç¿ë select case when x.ÅëÀå¹øÈ£ is not null then x.ÅëÀå¹øÈ£ else y.ÅëÀå¹øÈ£ end ÅëÀå¹øÈ£, case when x.¿¹±ÝÀÏÀÚ is not null then x.¿¹±ÝÀÏÀÚ else y.Ãâ±ÝÀÏÀÚ end ÀÔÃâ±ÝÀÏÀÚ, isnull(x.¿¹±Ý¾×, 0) ¿¹±Ý¾×, isnull(y.Ãâ±Ý¾×, 0) Ãâ±Ý¾× from ¿¹±Ý³»¿ª x full outer join Ãâ±Ý³»¿ª y on x.ÅëÀå¹øÈ£ = y.ÅëÀå¹øÈ£ and x.¿¹±ÝÀÏÀÚ = y.Ãâ±ÝÀÏÀÚ order by case when x.¿¹±ÝÀÏÀÚ is not null then x.¿¹±ÝÀÏÀÚ else y.Ãâ±ÝÀÏÀÚ end ÀÌ·±½ÄÀ¸·Î full outer joinÀ» »ç¿ëÇÏ¸é µÇÁö¸¸ °æ¿ì¿¡ µû¶ó¼´Â union À» ÅëÇؼµµ °¡´ÉÇÏ´Ù. 2. Union »ç¿ë select ÅëÀå¹øÈ£, ÀÔÃâ±ÝÀÏÀÚ, sum(¿¹±Ý¾×) ¿¹±Ý¾×, sum(Ãâ±Ý¾×) Ãâ±Ý¾× from ( select ÅëÀå¹øÈ£, ¿¹±ÝÀÏÀÚ as ÀÔÃâ±ÝÀÏÀÚ, ¿¹±Ý¾×, 0 as Ãâ±Ý¾× from ¿¹±Ý³»¿ª union all select ÅëÀå¹øÈ£, Ãâ±ÝÀÏÀÚ as ÀÔÃâ±ÝÀÏÀÚ, 0 as ¿¹±Ý¾×, Ãâ±Ý¾× from Ãâ±Ý³»¿ª ) x group by ÅëÀå¹øÈ£, ÀÔÃâ±ÝÀÏÀÚ order by ÀÔÃâ±ÝÀÏÀÚ ´Ù¾çÇÑ ÇØ°á¹æ¹ýÀ» ¾Ë°í °æ¿ì¿¡ µû¶ó¼ ÀûÀýÈ÷ »ç¿ëÇÏ¸é µÇ°Ú³×¿ä. /*-----------------------------------------------------------------------*/ 2-1-2. ½ÇÇà°èȹºÐ¸®ÀÇ union /*-----------------------------------------------------------------------*/ -- ¿¹Á¦1. select * from »ç¿ø where ÀÔ»çÀÏÀÚ like "2000%" and ºÎ¼ÄÚµå in (select ºÎ¼ÄÚµå from ºÎ¼ where ºÎ¼±¸ºÐ=1) |--Nested Loops(Left Semi Join, WHERE:([»ç¿ø].[ºÎ¼ÄÚµå]=[ºÎ¼].[ºÎ¼ÄÚµå])) |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([tempdb].[dbo].[»ç¿ø])) | |--Index Seek(OBJECT:([tempdb].[dbo].[»ç¿ø].[idx_ÀÔ»çÀÏÀÚ]), SEEK:([»ç¿ø].[ÀÔ»çÀÏÀÚ] >= "2000" AND [»ç¿ø].[ÀÔ»çÀÏÀÚ] < "200¼"), WHERE:(like([»ç¿ø].[ÀÔ»çÀÏÀÚ], "2000%", NULL)) ORDERED FORWARD) |--Index Seek(OBJECT:([tempdb].[dbo].[ºÎ¼].[idx_ºÎ¼±¸ºÐ]), SEEK:([ºÎ¼].[ºÎ¼±¸ºÐ]=1) ORDERED FORWARD) select * from »ç¿ø2 where ÀÔ»çÀÏÀÚ like "2000%" union select * from »ç¿ø2 where ºÎ¼ÄÚµå in (select ºÎ¼ÄÚµå from ºÎ¼ where ºÎ¼±¸ºÐ=1) |--Sort(DISTINCT ORDER BY:([Union1006] ASC, [Union1007] ASC, [Union1008] ASC, [Union1009] ASC, [Union1010] ASC)) |--Concatenation |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([tempdb].[dbo].[»ç¿ø2])) | |--Index Seek(OBJECT:([tempdb].[dbo].[»ç¿ø2].[idx_ÀÔ»çÀÏÀÚ]), SEEK:([»ç¿ø2].[ÀÔ»çÀÏÀÚ] >= "2000" AND [»ç¿ø2].[ÀÔ»çÀÏÀÚ] < "200¼"), WHERE:(like([»ç¿ø2].[ÀÔ»çÀÏÀÚ], "2000%", NULL)) ORDERED FORWARD) |--Bookmark Lookup(BOOKMARK:([Bmk1002]), OBJECT:([tempdb].[dbo].[»ç¿ø2])) |--Nested Loops(Inner Join, OUTER REFERENCES:([ºÎ¼].[ºÎ¼ÄÚµå])) |--Index Seek(OBJECT:([tempdb].[dbo].[ºÎ¼].[idx_ºÎ¼±¸ºÐ]), SEEK:([ºÎ¼].[ºÎ¼±¸ºÐ]=1) ORDERED FORWARD) |--Index Seek(OBJECT:([tempdb].[dbo].[»ç¿ø2].[idx_ºÎ¼ÄÚµå]), SEEK:([»ç¿ø2].[ºÎ¼ÄÚµå]=[ºÎ¼].[ºÎ¼ÄÚµå]) ORDERED FORWARD) ¿¹Á¦°¡ º°·ç ÁÁÁö¸øÇÏÁö¸¸ ÀÌ·±½ÄÀ¸·Îµµ °¢°¢ÀÇ À妽º¸¦ »ç¿ëÇÏ°Ô²û ÇÒ¼öµµÀÖ´Ù´Â°Í Á¤µµ¸¸ ¾Ë°íÀÖÀÚ. -- ¿¹Á¦2.(or¸¦ »ç¿ëÇÑ ¾ÈÁÁÀº ¹æ¹ýÀÌ´Ù.) »ç¿øÁ¤º¸¸¦ º¸¿©Áִ ȸé»ó¿¡¼ Á¶°Ç°ªÀ¸·Î »ç¿ø¹øÈ£¿Í ºÎ¼Äڵ带 ÀԷ¹޴ ȸéÀÌ ÀÖ´Ù°í °¡Á¤À» ÇÏ°í Äõ¸®¹®À» ¸¸µé¾î º¸ÀÚ.(µÑÁß Çϳª¸¸ ÀԷµȴÙ. - ¿É¼Ç¹Ú½º³ª ÅǵîÀ» ÀÌ¿ëÇÑ´Ù°í °¡Á¤) 1. °¡Àå ÆíÇÑ or¸¦ »ç¿ëÇÑ ¹æ¹ý --drop proc p1 create proc p1(@»ç¿ø¹øÈ£ int, @ºÎ¼ÄÚµå int) as select * from »ç¿ø where »ç¿ø¹øÈ£ = @»ç¿ø¹øÈ£ or ºÎ¼ÄÚµå = @ºÎ¼ÄÚµå go declare @»ç¿ø¹øÈ£ int, @ºÎ¼ÄÚµå int set @»ç¿ø¹øÈ£ = 3 set @ºÎ¼ÄÚµå = null exec p1 @»ç¿ø¹øÈ£, @ºÎ¼ÄÚµå |--Table Scan(OBJECT:([tempdb].[dbo].[»ç¿ø]), WHERE:([»ç¿ø].[»ç¿ø¹øÈ£]=[@»ç¿ø¹øÈ£] OR [»ç¿ø].[ºÎ¼ÄÚµå]=[@ºÎ¼ÄÚµå])) ÀÌ·±, ¼ÀÇà µ¥ÀÌÅÍ°¡ ¿ö³«¿¡ Àû´Ùº¸´Ï table scanÀ» ÇÏ³×¿ä µ¥ÀÌÅÍ·®ÀÌ ¸¹ÀÌ ÀÖ´Ù¸é ÀÌ·¸°Ô ¾ÈµÇ°í ¾Æ¸¶µµ »ç¿ø¹øÈ£À妽º¸¦ ÀÌ¿ëÇÏ°Ô²û ½ÇÇà°èȹÀÌ Ç®·ÈÀ» °ÍÀÌ´Ù. ±×·¸Áö¸¸ ´ÙÀ½¹ø Äõ¸®½Ã »ç¿ø¹øÈ£¸¦ null·Î ÇÏ°í ºÎ¼Äڵ带 ÀÔ·ÂÇÑ´Ù¸é ¾î¶»°Ô µÉ°ÍÀΰ¡...? 2. unionÀ» »ç¿ëÇÏ¿© ½ÇÇà°èȹ ºÐ¸® drop proc p1 --Áö¿ì°í ´Ù½Ã¸¸µéÀÚ go create proc p1(@»ç¿ø¹øÈ£ int, @ºÎ¼ÄÚµå int) as select * from »ç¿ø where @»ç¿ø¹øÈ£ is not null and »ç¿ø¹øÈ£ = @»ç¿ø¹øÈ£ union all select * from »ç¿ø where @»ç¿ø¹øÈ£ is null and ºÎ¼ÄÚµå = @ºÎ¼ÄÚµå go --»ç¿ø¹øÈ£°¡ ³Ñ¾î¿À¸é ¹«Á¶°Ç pk¸¦ »ç¿ëÇÏ°í, --±×·¸Áö ¾Ê´Ù¸é ºÎ¼ÄÚµå À妽º¸¦ »ç¿ëÇÏ°Ô²û ½ÇÇà°èȹÀ» ºÐ¸®ÇÏ¿´´Ù. --ÀÌ°æ¿ì union ÀÌ ¾Æ´Ï¶ó union all À» »ç¿ëÇÏ¿´´Ù. --ÀÌ·±½ÄÀÇ Äõ¸®¹®À» ¸¸µé¶§ ÁÖÀÇÇÒ°ÍÀº µÑÁßÇϳª¸¸ ÂüÀÌ¿©¾ß ÇÑ´Ù´Â °ÍÀÌ´Ù. declare @»ç¿ø¹øÈ£ int, @ºÎ¼ÄÚµå int set @»ç¿ø¹øÈ£ = 3 set @ºÎ¼ÄÚµå = null exec p1 @»ç¿ø¹øÈ£, @ºÎ¼ÄÚµå |--Concatenation |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([tempdb].[dbo].[»ç¿ø])) | |--Filter(WHERE:(STARTUP EXPR([@»ç¿ø¹øÈ£]<>NULL))) | |--Index Seek(OBJECT:([tempdb].[dbo].[»ç¿ø].[pk_»ç¿ø]), SEEK:([»ç¿ø].[»ç¿ø¹øÈ£]=[@»ç¿ø¹øÈ£]) ORDERED FORWARD) |--Bookmark Lookup(BOOKMARK:([Bmk1002]), OBJECT:([tempdb].[dbo].[»ç¿ø])) |--Filter(WHERE:(STARTUP EXPR([@»ç¿ø¹øÈ£]=NULL))) |--Index Seek(OBJECT:([tempdb].[dbo].[»ç¿ø].[idx_ºÎ¼ÄÚµå]), SEEK:([»ç¿ø].[ºÎ¼ÄÚµå]=[@ºÎ¼ÄÚµå]) ORDERED FORWARD) declare @»ç¿ø¹øÈ£ int, @ºÎ¼ÄÚµå int set @»ç¿ø¹øÈ£ = null set @ºÎ¼ÄÚµå = 1 exec p1 @»ç¿ø¹øÈ£, @ºÎ¼ÄÚµå |--Concatenation |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([tempdb].[dbo].[»ç¿ø])) | |--Filter(WHERE:(STARTUP EXPR([@»ç¿ø¹øÈ£]<>NULL))) | |--Index Seek(OBJECT:([tempdb].[dbo].[»ç¿ø].[pk_»ç¿ø]), SEEK:([»ç¿ø].[»ç¿ø¹øÈ£]=[@»ç¿ø¹øÈ£]) ORDERED FORWARD) |--Bookmark Lookup(BOOKMARK:([Bmk1002]), OBJECT:([tempdb].[dbo].[»ç¿ø])) |--Filter(WHERE:(STARTUP EXPR([@»ç¿ø¹øÈ£]=NULL))) |--Index Seek(OBJECT:([tempdb].[dbo].[»ç¿ø].[idx_ºÎ¼ÄÚµå]), SEEK:([»ç¿ø].[ºÎ¼ÄÚµå]=[@ºÎ¼ÄÚµå]) ORDERED FORWARD) µÎ°¡Áö °æ¿ì´Ù ¿øÇϴ´ë·Î Á¤È®È÷ ½ÇÇà°èȹÀÌ ºÐ¸®µÇ¾î ¾ðÁ¦³ª ¿øÇÏ´Â À妽º¸¦ Àß »ç¿ëÇÑ´Ù. 3.µ¿ÀûÄõ¸® »ç¿ë drop proc p1 --Áö¿ì°í ´Ù½Ã¸¸µéÀÚ go create proc p1(@»ç¿ø¹øÈ£ int, @ºÎ¼ÄÚµå int) as declare @sql varchar(1000) set @sql = "select * from »ç¿ø where " set @sql = @sql + case when @»ç¿ø¹øÈ£ is not null then " »ç¿ø¹øÈ£ = " + convert(varchar(10), @»ç¿ø¹øÈ£) else " ºÎ¼ÄÚµå = " + convert(varchar(10), @ºÎ¼ÄÚµå) end --print @sql exec (@sql) go declare @»ç¿ø¹øÈ£ int, @ºÎ¼ÄÚµå int set @»ç¿ø¹øÈ£ = 3 set @ºÎ¼ÄÚµå = null exec p1 @»ç¿ø¹øÈ£, @ºÎ¼ÄÚµå SELECT * FROM [»ç¿ø] WHERE [»ç¿ø¹øÈ£]=@1 |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([tempdb].[dbo].[»ç¿ø])) |--Index Seek(OBJECT:([tempdb].[dbo].[»ç¿ø].[pk_»ç¿ø]), SEEK:([»ç¿ø].[»ç¿ø¹øÈ£]=Convert([@1])) ORDERED FORWARD) declare @»ç¿ø¹øÈ£ int, @ºÎ¼ÄÚµå int set @»ç¿ø¹øÈ£ = null set @ºÎ¼ÄÚµå = 1 exec p1 @»ç¿ø¹øÈ£, @ºÎ¼ÄÚµå SELECT * FROM [»ç¿ø] WHERE [ºÎ¼ÄÚµå]=@1 |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([tempdb].[dbo].[»ç¿ø])) |--Index Seek(OBJECT:([tempdb].[dbo].[»ç¿ø].[idx_ºÎ¼ÄÚµå]), SEEK:([»ç¿ø].[ºÎ¼ÄÚµå]=Convert([@1])) ORDERED FORWARD) ÀÌ·±½ÄÀ¸·Î µ¿ÀûÄõ¸®¹®À» ¸¸µé¾î ½ÇÇàÀ» ÇÏ¸é ¸Å¹ø stored procedure¸¦ ÀçÄÄÆÄÀÏÇϸç ÇØ´çÇÏ´Â À妽º¸¦ »ç¿ëÇÏ¿© ¿øÇÏ´Â °á°ú¸¦ ¾òÀ»¼ö ÀÖ´Ù. ÇÏÁö¸¸ ÀÌ·±½ÄÀ̶ó¸é stored procedure¸¦ »ç¿ëÇÏ´Â È¿°ú¸¦ Á¦´ë·Î º¼¼ö¾ø´Ù. ¾î¶² ¹æ½ÄÀÌ ÁÁÀ»Áö´Â °¢ÀÚ ÆÇ´ÜÇÏÀÚ. -- ¿¹Á¦3. (¿ä¹ø¿¡´Â like¸¦ »ç¿ëÇÑ ¾ÈÁÁÀº ¹æ¹ýÀÌ´Ù). »ç¿øÁ¤º¸¸¦ º¸¿©Áִ ȸé»ó¿¡¼ Á¶°Ç°ªÀ¸·Î »ç¿øÀ̸§°ú ÀÔ»ç¿ùÀ» ÀԷ¹޴ ȸéÀÌ ÀÖ´Ù°í °¡Á¤À» ÇÏ°í Äõ¸®¹®À» ¸¸µé¾î º¸ÀÚ.(µÑÁß Çϳª¸¸ ÀԷµȴÙ. - ¿É¼Ç¹Ú½º³ª ÅǵîÀ» ÀÌ¿ëÇÑ´Ù°í °¡Á¤) 1. °¡Àå ÆíÇÑ like ¹æ¹ý --drop proc p2 create proc p2(@À̸§ varchar(10), @ÀÔ»çÀÏÀÚ varchar(8)) as select * from »ç¿ø where À̸§ like @À̸§ or ÀÔ»çÀÏÀÚ like @ÀÔ»çÀÏÀÚ go declare @À̸§ varchar(10), @ÀÔ»çÀÏÀÚ varchar(8) set @À̸§ = "¯%" set @ÀÔ»çÀÏÀÚ = null exec p2 @À̸§, @ÀÔ»çÀÏÀÚ |--Table Scan(OBJECT:([tempdb].[dbo].[»ç¿ø]), WHERE:(like([»ç¿ø].[À̸§], [@À̸§], NULL) OR like([»ç¿ø].[ÀÔ»çÀÏÀÚ], [@ÀÔ»çÀÏÀÚ], NULL))) ÀÌ·±, ¼ÀÇà µ¥ÀÌÅÍ°¡ ¿ö³«¿¡ Àû´Ùº¸´Ï table scanÀ» ÇÏ³×¿ä µ¥ÀÌÅÍ·®ÀÌ ¸¹ÀÌ ÀÖ´Ù¸é ÀÌ·¸°Ô ¾ÈµÇ°í ¾Æ¸¶µµ À̸§À妽º¸¦ ÀÌ¿ëÇÏ°Ô²û ½ÇÇà°èȹÀÌ Ç®·ÈÀ» °ÍÀÌ´Ù. ±×·¸Áö¸¸ ´ÙÀ½¹ø Äõ¸®½Ã À̸§À» null·Î ÇÏ°í ÀÔ»çÀÏÀÚ¸¦ ÀÔ·ÂÇÑ´Ù¸é ¾î¶»°Ô µÉ°ÍÀΰ¡...? 2. unionÀ» »ç¿ëÇÏ¿© ½ÇÇà°èȹ ºÐ¸® drop proc p2 --Áö¿ì°í ´Ù½Ã¸¸µéÀÚ go create proc p2(@À̸§ varchar(10), @ÀÔ»çÀÏÀÚ varchar(8)) as select * from »ç¿ø where À̸§ like @À̸§ and @À̸§ is not null union all select * from »ç¿ø where ÀÔ»çÀÏÀÚ like @ÀÔ»çÀÏÀÚ and @À̸§ is null go --À̸§ÀÌ ³Ñ¾î¿À¸é ¹«Á¶°Ç À̸§À妽º¸¦ »ç¿ëÇÏ°í, --±×·¸Áö ¾Ê´Ù¸é ÀÔ»çÀÏÀÚÀ妽º¸¦ »ç¿ëÇÏ°Ô²û ½ÇÇà°èȹÀ» ºÐ¸®ÇÏ¿´´Ù. --ÀÌ°æ¿ì union ÀÌ ¾Æ´Ï¶ó union all À» »ç¿ëÇÏ¿´´Ù. --ÀÌ·±½ÄÀÇ Äõ¸®¹®À» ¸¸µé¶§ ÁÖÀÇÇÒ°ÍÀº µÑÁßÇϳª¸¸ ÂüÀÌ¿©¾ß ÇÑ´Ù´Â °ÍÀÌ´Ù. declare @À̸§ varchar(10), @ÀÔ»çÀÏÀÚ varchar(8) set @À̸§ = "¯%" set @ÀÔ»çÀÏÀÚ = null exec p2 @À̸§, @ÀÔ»çÀÏÀÚ |--Concatenation |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([tempdb].[dbo].[»ç¿ø])) | |--Filter(WHERE:(STARTUP EXPR([@À̸§]<>NULL))) | |--Nested Loops(Inner Join, OUTER REFERENCES:(LikeRangeStart([@À̸§], NULL), LikeRangeEnd([@À̸§], NULL), LikeRangeInfo([@À̸§], NULL))) | |--Compute Scalar(DEFINE:([Expr1009]=LikeRangeStart([@À̸§], NULL), [Expr1011]=LikeRangeEnd([@À̸§], NULL), [Expr1013]=LikeRangeInfo([@À̸§], NULL))) | | |--Constant Scan | |--Index Seek(OBJECT:([tempdb].[dbo].[»ç¿ø].[idx_À̸§]), SEEK:([»ç¿ø].[À̸§] > LikeRangeStart([@À̸§], NULL) AND [»ç¿ø].[À̸§] < LikeRangeEnd([@À̸§], NULL)), WHERE:(like([»ç¿ø].[À̸§], [@À̸§], NULL)) ORDERED FORWARD) |--Bookmark Lookup(BOOKMARK:([Bmk1002]), OBJECT:([tempdb].[dbo].[»ç¿ø])) |--Filter(WHERE:(STARTUP EXPR([@À̸§]=NULL))) |--Nested Loops(Inner Join, OUTER REFERENCES:([Expr1026], [Expr1027], LikeRangeInfo([@ÀÔ»çÀÏÀÚ], NULL))) |--Compute Scalar(DEFINE:([Expr1026]=Convert(LikeRangeStart([@ÀÔ»çÀÏÀÚ], NULL)), [Expr1027]=Convert(LikeRangeEnd([@ÀÔ»çÀÏÀÚ], NULL)), [Expr1020]=LikeRangeInfo([@ÀÔ»çÀÏÀÚ], NULL))) | |--Constant Scan |--Index Seek(OBJECT:([tempdb].[dbo].[»ç¿ø].[idx_ÀÔ»çÀÏÀÚ]), SEEK:([»ç¿ø].[ÀÔ»çÀÏÀÚ] > [Expr1026] AND [»ç¿ø].[ÀÔ»çÀÏÀÚ] < [Expr1027]), WHERE:(like([»ç¿ø].[ÀÔ»çÀÏÀÚ], [@ÀÔ»çÀÏÀÚ], NULL)) ORDERED FORWARD) declare @À̸§ varchar(10), @ÀÔ»çÀÏÀÚ varchar(8) set @À̸§ = null set @ÀÔ»çÀÏÀÚ = "2000%" exec p2 @À̸§, @ÀÔ»çÀÏÀÚ |--Concatenation |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([tempdb].[dbo].[»ç¿ø])) | |--Filter(WHERE:(STARTUP EXPR([@À̸§]<>NULL))) | |--Nested Loops(Inner Join, OUTER REFERENCES:(LikeRangeStart([@À̸§], NULL), LikeRangeEnd([@À̸§], NULL), LikeRangeInfo([@À̸§], NULL))) | |--Compute Scalar(DEFINE:([Expr1009]=LikeRangeStart([@À̸§], NULL), [Expr1011]=LikeRangeEnd([@À̸§], NULL), [Expr1013]=LikeRangeInfo([@À̸§], NULL))) | | |--Constant Scan | |--Index Seek(OBJECT:([tempdb].[dbo].[»ç¿ø].[idx_À̸§]), SEEK:([»ç¿ø].[À̸§] > LikeRangeStart([@À̸§], NULL) AND [»ç¿ø].[À̸§] < LikeRangeEnd([@À̸§], NULL)), WHERE:(like([»ç¿ø].[À̸§], [@À̸§], NULL)) ORDERED FORWARD) |--Bookmark Lookup(BOOKMARK:([Bmk1002]), OBJECT:([tempdb].[dbo].[»ç¿ø])) |--Filter(WHERE:(STARTUP EXPR([@À̸§]=NULL))) |--Nested Loops(Inner Join, OUTER REFERENCES:([Expr1026], [Expr1027], LikeRangeInfo([@ÀÔ»çÀÏÀÚ], NULL))) |--Compute Scalar(DEFINE:([Expr1026]=Convert(LikeRangeStart([@ÀÔ»çÀÏÀÚ], NULL)), [Expr1027]=Convert(LikeRangeEnd([@ÀÔ»çÀÏÀÚ], NULL)), [Expr1020]=LikeRangeInfo([@ÀÔ»çÀÏÀÚ], NULL))) | |--Constant Scan |--Index Seek(OBJECT:([tempdb].[dbo].[»ç¿ø].[idx_ÀÔ»çÀÏÀÚ]), SEEK:([»ç¿ø].[ÀÔ»çÀÏÀÚ] > [Expr1026] AND [»ç¿ø].[ÀÔ»çÀÏÀÚ] < [Expr1027]), WHERE:(like([»ç¿ø].[ÀÔ»çÀÏÀÚ], [@ÀÔ»çÀÏÀÚ], NULL)) ORDERED FORWARD) µÎ°¡Áö °æ¿ì´Ù ¿øÇϴ´ë·Î Á¤È®È÷ ½ÇÇà°èȹÀÌ ºÐ¸®µÇ¾î ¾ðÁ¦³ª À妽º¸¦ Àß »ç¿ëÇÑ´Ù. ÀÌ·±½ÄÀÇ union À» »ç¿ëÇÑ ½ÇÇà°èȹ ºÐ¸®´Â À¯¿ëÇÏ´Ï Àß ÀÍÇôµÎ¼¼¿ä. 3.µ¿ÀûÄõ¸® »ç¿ë drop proc p2 --Áö¿ì°í ´Ù½Ã¸¸µéÀÚ go create proc p2(@À̸§ varchar(10), @ÀÔ»çÀÏÀÚ varchar(8)) as declare @sql varchar(1000) set @sql = "select * from »ç¿ø where " set @sql = @sql + case when @À̸§ is not null then " À̸§ like """ + @À̸§ + """" else "
|