CTE ve SubQuery arasındaki fark nedir?


143

Bu gönderiden Aşağıdaki yordamda ROW_NUMBER nasıl kullanılır?

Aynı sorunu çözmek için biri sub-queryve diğerinin a kullandığı yanıtların iki sürümü vardır CTE.

Şimdi, CTE (Common Table Expression)bir 'alt sorgu ' üzerinden bir avantaj kullanmanın avantajı nedir (böylece, sorgunun gerçekte ne yaptığını daha okunabilir )

Bir kullanmanın tek avantajı CTEover sub-selectaslında olmasıdır isimsub-query . Bir CTE basit (özyinelemesiz) CTE olarak kullanıldığında bu ikisi arasında başka farklar var mı?


İyi tartışma ile türev soru: stackoverflow.com/q/11169550/781695
kullanıcı

7
IMO, bir CTE düşünen kimse var mı az örülmüş alt sorgular dev damla kurumsal veri yönetimi sistemlerinin çoğunda genelinde kullanımda testere dişleri şeklindeki sorguları kafa karıştırıcı çöp yığını görmediği okunabilir. Büyük, önemsiz olmayan sorguların daha sonra veya yeni gözlerle okunması, alt sorgulardan çok daha kolaydır ve en azından Postgres söz konusu olduğunda birçok durumda sihirli bir şekilde daha iyi performans gösterir . ([Tam olarak anlamadığım nedenlerden dolayı [( stackoverflow.com/questions/33731068/… ), tam tersi daha olası görünüyor.)
zxq9

Yanıtlar:


102

Basit (özyinelemeli olmayan) CTE sürümlerine karşı alt sorguda , muhtemelen çok benzerler. Herhangi bir farklılığı tespit etmek için profil oluşturucu ve gerçek yürütme planını kullanmanız gerekir ve bu da kurulumunuza özgü olacaktır (bu yüzden size cevabı tam olarak söyleyemeyiz).

Olarak , genel ; Bir CTE tekrar tekrar kullanılabilir; bir alt sorgu yapılamaz. Bu onları özellikle ağaç yapılarına uygun hale getirir.


1
Özür dilerim, sorumda daha açık olmalıydım. CTE'nin LIKE alt sorgusunun kullanıldığı bağlamda CTE ve Subquery arasındaki fark nedir?
dance2die

2
@Marc Gravell: Profillerin davranışı garanti edilmediğinden, CTE'nin davranışına karşı (değerlendirme açısından) bundan daha fazlasını yapabiliriz.
casperOne

1
Bu ifadenin CTS ve alt sorgu farkına bakan insanlar için ne kadar anlamlı olduğundan emin değilim A CTE can be used recursively; a sub-query cannot. Bir örnek harika olurdu.
Aniket Thakur

88

Ortak Tablo İfadesinin ana avantajı ( yinelemeli sorgular için kullanılmadığında ), alt sorguyu kullanmak istediğiniz her yerde bildirmek yerine kapsüllemedir, bir kez tanımlayabilirsiniz, ancak birden çok referansınız vardır. ona.

Ancak bu yok değil sadece bir defa çalıştırılır anlamına (uyarınca bu çok cevabın önceki tekrarlamalar , yorumladı tüm olanlara teşekkür ederim). Sorgu kesinlikle birden çok kez başvurulursa birden çok kez yürütülme potansiyeline sahiptir; sorgu optimize edici sonuçta CTE'nin nasıl yorumlanması gerektiğine karar verir.


"CTE'yi geçici tablo değişkeni olarak düşün", CTE'nin diskte veya bellekte saklandığı anlamına mı geliyor?
dance2die

CTE'yi veya alt sorguyu tanım gereği birden çok sorguda kullanamazsınız. Optimize edici, alt sorguyu CTE ile aynı şekilde işlediğinden eminim (1 sorguda kaç kez kullanıldığına bakılmaksızın, sonuç kümesini yalnızca bir kez değerlendirerek)
AlexCuse

@AlexCuse: Sanırım CTE'nin bağlamını yeterince açıkladım, ancak daha fazla açıklamak için daha fazla şey ekledim.
casperOne

@AlexCuse: CTE veya alt sorgunun birden fazla yerde kullanılabileceğine dair herhangi bir ima da yoktur. CTE ve optimizer arasındaki fark, CTE'nin davranışının garanti altına alınması, optimizasyonun davranışının garanti edilmemesidir.
casperOne

ve optimize edicinin boğulduğu ve alt sorgunun birden fazla değerlendirildiği bazı uç durumlar olabileceğine karar vereceğim, yine de hiç karşılaşmadım. Sonra tekrar, yapabildiğim her yerde
CTE'leri kullanıyorum

15

CTEen çok özyineleme için yararlıdır:

WITH hier(cnt) AS (
        SELECT  1
        UNION ALL
        SELECT  cnt + 1
        FROM    hier
        WHERE   cnt < @n
        )
SELECT  cnt
FROM    hier

@nsatırları (en fazla 101) döndürür . Takvimler, kukla satır kümeleri vb. İçin kullanışlıdır.

Onlar da daha okunabilir (bence).

Bunun dışında, CTEve subqueriesaynıdır.


MSSQL, bir noktalı virgül (;) İLE eklemeniz gerekir, sipariş akıllıca bir hata alırsınız. olması gerekir;WITH blabla AS ...)
Obinna Nnenanya

2
@ObinnaNnenanya: yalnızca toplu işteki ilk ifade değilse. Noktalı virgül ile ifadeleri Sonlandırma SQL Server önce dışındaki cari versiyonlarında bunu zorlamaz rağmen yine de iyi bir fikirdir WITH, MERGEve benzeri
Quassnoi

10

Bahsedilmeyen bir fark, bir birliğin birkaç bölümünde tek bir CTE'ye atıfta bulunulmasıdır


8

Bir şeyi kaçırmadıkça, CTE'leri ve alt sorguları da kolayca adlandırabilirsiniz.

Sanırım ana fark okunabilirlik (CTE'yi daha okunabilir buluyorum çünkü alt sorunuzu ortadan ziyade ön tarafta tanımlar).

Ve özyineleme ile herhangi bir şey yapmanız gerekiyorsa, bunu bir alt sorgu ile yapmakta biraz sorun yaşarsınız;)


1
Emin orada değilim herhangi (ı belli durumlarda yürütme planında ufak farklılıklar olabilir bekliyoruz gerçi) olmayan estetik farkı. Beni aydınlatmak ister misin?
AlexCuse

2
Sen edebilirsiniz isim CTEs, ama sadece can takma subqueries. Fark, CTE'leri birden fazla takma adla tekrar kullanabilirsiniz (cf. @ Michael Petito'nun casperOne'a yaptığı açıklamada örnek). Bunu alt sorgularla yapmanın bir yolunu bilmiyorum.
kmote

7

Kimsenin bahsetmediği önemli bir gerçek (en azından postgreslerde), CTE'lerin optimizasyon çitleri olduğudur:

https://blog.2ndquadrant.com/postgresql-ctes-are-optimization-fences/

Yani, tüm sorgu planına katlanmak yerine kendi atomik sorguları olarak ele alınacaklardır. Daha iyi bir açıklama yapmak için uzmanlığım yok, ancak kullandığınız sql sürümü için semantiği kontrol etmelisiniz; ileri düzey kullanıcılar için, bir optimizasyon çiti oluşturabilmek sorgu planlayıcısını kontrol etme konusunda uzman seviyeniz varsa performansa yardımcı olabilir; Bununla birlikte, vakaların% 99'unda sorgu planlayıcısına ne yapması gerektiğini söylemekten kaçınmalısınız, çünkü daha hızlı olacağını düşündüğünüz şey muhtemelen daha hızlı olacağını düşündüğünden daha kötüdür. :-)


6

Başkalarının cevaplarına ek olarak, birkaç kez kullanılan bir ve aynı alt sorgunuz varsa, tüm bu alt sorguları tek bir CTE ile değiştirebilirsiniz. Bu, kodunuzu daha iyi kullanmanızı sağlar.


4

Anlamanız gereken bir şey de SQL Server'ın eski sürümlerinde (evet, birçok insan hala SQL Server 2000 veritabanlarını desteklemelidir), CTE'lere izin verilmez ve daha sonra türetilmiş tablo en iyi çözümdür.


2

İPUCU: (MAKSİMUM n)

belirli bir ifadede izin verilen özyineleme düzeylerinin sayısını , maddede MAXRECURSIONipucu ve 0 ile 32.767 arasında bir değer kullanarak sınırlayabilirsiniz.OPTION

Örneğin, deneyebilirsiniz:

OPTION 
      (MAXRECURSION 150)

GO
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.