ON yan tümcesinin konumu aslında ne anlama geliyor?


23

Normal JOIN ... ON ...sözdizimi iyi bilinmektedir. Ancak, ONmaddeyi yazdıklarından ayrı olarak yerleştirmek de mümkündür JOIN. Bu, pratikte nadir görülen, öğreticilerde bulunmayan bir şeydir ve bunun mümkün olabileceğinden bahseden herhangi bir web kaynağı bulamadım .

İşte oynayabileceğiniz bir betik:

SELECT *
INTO #widgets1
FROM (VALUES (1), (2), (3)) x(WidgetID)


SELECT *
INTO #widgets2
FROM (VALUES (1, 'SomeValue1'), (2, 'SomeValue2'), (3, 'SomeValue3')) x(WidgetID, SomeValue)

SELECT *
INTO #widgetProperties
FROM (VALUES
    (1, 'a'), (1, 'b'),
    (2, 'a'), (2, 'b'))
x(WidgetID, PropertyName)


--q1
SELECT w1.WidgetID, w2.SomeValue, wp.PropertyName
FROM #widgets1 w1
LEFT JOIN #widgets2 w2 ON w2.WidgetID = w1.WidgetID
LEFT JOIN #widgetProperties wp ON w2.WidgetID = wp.WidgetID AND wp.PropertyName = 'b'
ORDER BY w1.WidgetID


--q2
SELECT w1.WidgetID, w2.SomeValue, wp.PropertyName
FROM #widgets1 w1
LEFT JOIN #widgets2 w2 --no ON clause here
JOIN #widgetProperties wp
 ON w2.WidgetID = wp.WidgetID AND wp.PropertyName = 'b'
 ON w2.WidgetID = w1.WidgetID
ORDER BY w1.WidgetID


--q3
SELECT w1.WidgetID, w2.SomeValue, wp.PropertyName
FROM #widgets1 w1
LEFT JOIN (
    #widgets2 w2 --no SELECT or FROM here
    JOIN #widgetProperties wp
    ON w2.WidgetID = wp.WidgetID AND wp.PropertyName = 'b')
ON w2.WidgetID = w1.WidgetID
ORDER BY w1.WidgetID

q1 normal görünüyor. q2 ve q3, fıkraların olağandışı konumlarına sahiptir ON.

Bu senaryo mutlaka anlam ifade etmiyor. Anlamlı bir senaryo benim için zordu.

Peki bu olağandışı sözdizimi kalıpları ne anlama geliyor? Bu nasıl tanımlanır? İki ONmaddenin tüm pozisyonlarına ve siparişlerine izin verilmediğini fark ettim . Bunu düzenleyen kurallar nelerdir?

Ayrıca böyle sorular yazmak hiç iyi bir fikir değil mi?

Yanıtlar:


32

FROMFıkra sözdizimi şemasına bakarsanız fıkra için sadece bir yer olduğunu göreceksiniz ON:

<joined_table> ::= 
{
    <table_source> <join_type> <table_source> ON <search_condition> 
    ...
}

Ne kafa karıştırıcı bulmak, basit özyineleme çünkü <table_source>içinde<joined_table > Yukarıdaki başka olabilir <joined_table>:

[ FROM { <table_source> } [ ,...n ] ] 
<table_source> ::= 
{
    table_or_view_name ... 
    ...
    | <joined_table> 
    ...
}

Karışıklığı önlemek için, görsel olarak ayırmak için açık olmayan durumlarda (örnekleriniz gibi) parantez kullanmalısınız <table_sources>; Sorgu çözümleyici için gerekli değil, insanlar için faydalıdırlar.


33

Birleşmede yer alan mantıksal tabloları belirler.

Basit bir örnekle

SELECT w1.WidgetID,
       w2.SomeValue,
       wp.PropertyName
FROM   #widgets1 w1
       LEFT JOIN #widgets2 w2
         ON w2.WidgetID = w1.WidgetID
       JOIN #widgetProperties wp
         ON w2.WidgetID = wp.WidgetID
            AND wp.PropertyName = 'b'
ORDER  BY w1.WidgetID 

#widgets1dışa bırakılır #widgets2- bunun sonucu içine birleştirilen sanal bir tablo oluşturur #widgetProperties. Öngörü w2.WidgetID = wp.WidgetID, ilk dış birleşmeden gelen boş uzamış satırların filtrelenerek, tüm birleşimlerin iç birleşmelerini etkin bir şekilde yapması anlamına gelecektir.

Bu, ikinci çeyrekten farklı ...

SELECT w1.WidgetID,
       w2.SomeValue,
       wp.PropertyName
FROM   #widgets1 w1
       LEFT JOIN #widgets2 w2 --no ON clause here
                 JOIN #widgetProperties wp
                   ON w2.WidgetID = wp.WidgetID
                      AND wp.PropertyName = 'b'
         ON w2.WidgetID = w1.WidgetID
ORDER  BY w1.WidgetID

#widgets2iç kısım birleştirilmiştir #widgetProperties. Bu birleşimden kaynaklanan sanal tablo, Sol Dış Birleşimdeki sağdaki tablodur.#widgets1

Aynı sonuç, türetilmiş bir tablo veya Ortak Tablo İfadesi kullanılarak da elde edilebilir ...

WITH VT2
     AS (SELECT w2.WidgetID,
                w2.SomeValue,
                wp.PropertyName
         FROM   #widgets2 w2 
                JOIN #widgetProperties wp
                  ON w2.WidgetID = wp.WidgetID
                     AND wp.PropertyName = 'b')
SELECT w1.WidgetID,
       VT2.SomeValue,
       VT2.PropertyName
FROM   #widgets1 w1
       LEFT JOIN VT2
         ON VT2.WidgetID = w1.WidgetID
ORDER  BY w1.WidgetID 

... Veya alternatif olarak, sanal tabloları yeniden sipariş edip RIGHT JOINyerine kullanabilirsiniz .

SELECT w1.WidgetID,
       w2.SomeValue,
       wp.PropertyName
FROM   #widgets2 w2
       INNER JOIN #widgetProperties wp
               ON w2.WidgetID = wp.WidgetID
                  AND wp.PropertyName = 'b'
       RIGHT JOIN #widgets1 w1
               ON w2.WidgetID = w1.WidgetID
ORDER  BY w1.WidgetID 

Bu, burada Itzik Ben Gan tarafından kapsanmaktadır.

... JOIN koşulları, masa düzeni ile chiastik bir ilişki izlemelidir. Diğer bir deyişle, bu sırayla T1, T2, T3 ve T4 tablolarını belirtirseniz ve JOIN koşulları T1 ile T2, T2 ve T3 ile T3 ile eşleşirse, JOIN koşullarını tablo sırasının tersi sırayla belirtmeniz gerekir. , bunun gibi:

FROM   T1
       <join_type> T2 T2
                  <join_type> T3 T3
                             <join_type> T4
                               ON T4.key = T3.key
                    ON T3.key = T2.key
         ON T2.key = T1.key 

Bu birleştirme tekniğine farklı bir şekilde bakmak için, belirli bir JOIN koşulu, yalnızca hemen üzerindeki tablo adlarına veya daha önce JOIN koşullarının daha önce bahsedilen ve çözülen tablo adlarına başvurabilir.

ancak makalede bazı yanlışlıklar var, Lubor Kollar'ın takip mektubuna da bakın.


Teşekkürler Martin, bu cevap çok yardımcı oldu. Yine de diğerini kabul edeceğim, çünkü resmi dilbilgisi konusundaki amacı konuyu tam olarak anlamama yardımcı oldu. Özellikle “chiastic ilişki” yanlış bir fikir gibi görünüyor. Bu bir ağaçtır, liste değil tersine çevrilmiş bir listedir. mustaccio, Itziks'in yorumunun neden doğru olmadığını anlamak için bir çerçeve oluşturdu.
boot4life
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.