Daha çok ilişkili bir alt sorgu gibi
Bir LATERAL(Postgres 9.3 veya üzeri) daha fazla gibi birleştirme ilişkili alt sorgu , bir düz alt sorgu. Andomar'ın işaret ettiği gibi , LATERALbirleştirmenin sağındaki bir işlev veya alt sorgu, soldaki her satır için bir kez değerlendirilmelidir - tıpkı ilişkili bir alt sorgu gibi - düz bir alt sorgu (tablo ifadesi) yalnızca bir kez değerlendirilir . (Sorgu planlayıcısının,
her ikisi için de performansı optimize etmenin yolları vardır.) Bu ilgili yanıt, aynı sorunu çözerek her iki taraf için de kod örneklerine sahiptir:
Birden fazla sütun döndürmek için bir LATERALbirleştirme genellikle daha basit, daha temiz ve daha hızlıdır.
Ayrıca, ilişkili bir alt sorgunun eşdeğeri olduğunu unutmayın LEFT JOIN LATERAL ... ON true:
Üzerindeki kılavuzu okuyun LATERAL
Burada cevaplara koyacağımız her şeyden daha otoriter:
Bir alt sorgunun yapamayacağı şeyler
Orada olan bir bu işler LATERALyapabilir katılmak, ancak bir (korelasyon) alt sorgu (kolayca) olamaz. İlişkili bir alt sorgu, çıplak işlev çağrıları (birden çok satır döndürürlerse sonuç satırlarını çoğaltır) hariç, yalnızca tek bir değer döndürür, birden çok sütun değil, birden çok satır döndüremez. Ancak bazı set-döndürme işlevlerine bile sadece FROMmaddede izin verilir . unnest()Postgres 9.4 veya sonraki sürümlerde çoklu parametrelerde olduğu gibi . Kullanım kılavuzu:
Buna sadece FROMmaddede izin verilir ;
Bu işe yarar, ancak kolayca bir alt sorgu ile değiştirilemez:
CREATE TABLE tbl (a1 int[], a2 int[]);
SELECT * FROM tbl, unnest(a1, a2) u(elem1, elem2); -- implicit LATERAL
Madde içindeki virgül ( ,) FROMkısa gösterimdir CROSS JOIN.
LATERALtablo işlevleri için otomatik olarak kabul edilir.
Özel durum hakkında daha fazla bilgi UNNEST( array_expression [, ... ] ):
SELECTListedeki geri dönen işlevler
Ayrıca gibi set dönen işlevleri kullanabilirsiniz unnest()içinde SELECTdoğrudan listeye. Bu, aynı SELECTlistede Postgres 9.6'ya kadar birden fazla işlevle şaşırtıcı davranışlar sergilemek için kullanılır . Ancak sonunda Postgres 10 ile sterilize edildi ve şu anda geçerli bir alternatif (standart SQL olmasa bile). Görmek:
Yukarıdaki örneğe dayanarak:
SELECT *, unnest(a1) AS elem1, unnest(a2) AS elem2
FROM tbl;
karşılaştırma:
pg 9.6 için dbfiddle burada
pg 10 dbfiddle burada
Yanlış bilgileri netleştirin
Kullanım kılavuzu:
İçin INNERve OUTERbirleştirme türleri, bir durumdur, yani tam olarak biri belirtilmelidir katılması NATURAL, ON join_condition veya USING( join_column [...]). Anlam için aşağıya bakın.
Çünkü CROSS JOIN, bu maddelerin hiçbiri görünmez.
Dolayısıyla bu iki sorgu geçerlidir (özellikle yararlı olmasa bile):
SELECT *
FROM tbl t
LEFT JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t ON TRUE;
SELECT *
FROM tbl t, LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;
Bu olmasa da:
SELECT *
FROM tbl t
LEFT JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;
Bu yüzden Andomar en @ kod örneği doğrudur ( CROSS JOINbir birleşim koşulu gerektirmez) ve Attila'nın @ DİR geçersiz oldu.
applyaynıdırlateral)