Alias ​​Subkueri sama dengan alias kueri utama

23

Saya punya query SQL yang alias sama dengan beberapa alias subquerynya.

Sebagai contoh:

select *
from ROOM r
where ...
         (
              select *
              from ROAD r
              where ...
         )

Ini berfungsi dengan baik, karena alias subquery tampaknya menyembunyikan yang utama.

  1. Apakah akan bekerja seperti itu dalam semua kasus?
  2. Apakah saya akan mendapatkan hasil yang tidak ditentukan?
  3. Jika tidak apa-apa untuk melakukan itu, bagaimana saya bisa membuat referensi ke pertanyaan utama r?
IcySnow
sumber
1
Jawaban singkatnya adalah "1.Ya", "2.No" dan "3.dalam hal ini, Anda tidak dapat (jadi tidak benar-benar OK jika Anda ingin membuat referensi seperti itu)"
ypercubeᵀᴹ

Jawaban:

15

Tidak apa-apa untuk subqueries bersarang untuk menggunakan alias yang sama seperti yang digunakan dalam kueri induk, meskipun mungkin agak membingungkan bagi seseorang yang membaca kode. Ruang nama untuk alias di subquery bersarang terpisah dari ruang nama di induk. Misalnya kueri di bawah ini memiliki subquery bersarang byang juga memiliki alias yang bdigunakan di dalamnya. Ini berpotensi membingungkan bagi programmer tetapi tidak masalah dengan mesin DBMS:

   select a.foo
          ,b.bar
          ,b.BarCount
      from (select b.bar
                  ,count (*) as BarCount
              from BarTable b
              join OtherTable o
                on b.OtherTableID = o.OtherTableID
             group by b.bar) b
      join Foobar a
        on a.bar = b.bar

Pada subquery berkorelasi Anda memiliki akses ke alias induk, sehingga alias harus unik di kueri induk dan subquery berkorelasi. Jika kami mengambil subquery berkorelasi seperti yang di bawah ini, kami memiliki satu ruang nama global yang dibagi antara kueri induk dan subquery yang berkorelasi:

select a.foo
      ,b.bar
  from Foobar a
  join Bar b
    on b.FooBarID = a.FooBarID
 where not exists
       (select 1
          from Bar b2
         where b2.BarCategoryID = b.BarCategoryID
           and b2.BarDate > b.BarDate)

Subquery yang dikorelasikan tidak memiliki alias karena tidak berpartisipasi dalam suatu join 1 . Referensi bdan b2untuk barkeduanya tersedia untuk subquery karena subquery yang dikorelasikan berbagi namespace mereka untuk alias dengan induk.


1 Perhatikan bahwa pengoptimal dapat memilih untuk menggunakan operator gabungan dalam rencana di belakang layar, meskipun operasi sebenarnya yang ditentukan adalah subquery berkorelasi dan bukan gabungan terhadap subquery bersarang.

ConcernedOfTunbridgeWells
sumber
Subquery dalam kueri pertama adalah tabel turunan dan standar SQL mengharuskannya untuk selalu diberi nama: tidak ada alasan logis untuk persyaratan ini tetapi SQL Server telah menerapkannya, meskipun dalam contoh khusus Anda telah memilih nama memang wajib. Subquery dalam kueri kedua bukanlah tabel turunan, karenanya mengapa ia tidak memerlukan nama (fakta bahwa itu adalah subquery yang berkorelasi tidak penting).
onedaywhen
@onedaywhen - Saya tidak bisa memikirkan situasi apa pun kecuali subquery berkorelasi di mana subquery membutuhkan akses ke alias yang digunakan dalam orangtua. Apakah Anda memiliki sesuatu yang spesifik dalam pikiran?
ConcernedOfTunbridgeWells
Saya tidak yakin saya mengerti pertanyaan Anda. Mungkin saya harus menjelaskan bahwa saya secara khusus menanggapi komentar Anda, "Subquery yang dikorelasikan tidak memiliki alias karena tidak berpartisipasi dalam bergabung seperti itu." Respons saya seharusnya menyampaikan poin bahwa aturan mengenai variabel rentang (apa yang standar SQL sebut 'nama korelasi' dan Anda sebut 'alias') tidak secara langsung terkait dengan partisipasi mereka (atau sebaliknya) dalam bergabung.
onedaywhen
Contoh sederhana: SELECT * FROM ( SELECT c FROM T ) AS T2;- tidak ada yang bergabung, belum ada korelasi dengan standar SQL yang mensyaratkan bahwa tabel yang diturunkan diberi variabel rentang ( T2dalam hal ini).
onedaywhen
3

ConcernedOfTunbridgeWells, Anda menulis (penekanan saya): "Pada subquery berkorelasi Anda memiliki akses ke alias orangtua, sehingga alias harus unik di kueri induk dan subquery berkorelasi."

Saya tidak percaya keunikan diperlukan. Saya percaya bahwa, jika alias digunakan dalam subquery berkorelasi sebagai nama korelasi, serta alias tabel dalam kueri luar, alias dalam subquery akan diutamakan.

Contoh:

CREATE TABLE #T (A INT)
CREATE TABLE #U (A INT)
CREATE TABLE #V (A INT)

INSERT INTO #T (A) VALUES (1), (2), (3)
INSERT INTO #U (A) VALUES (2), (3), (4)
INSERT INTO #V (A) VALUES (3), (4), (5)

SELECT
    T1.A
FROM
    #T AS T1
    INNER JOIN #U AS T2 ON T1.A = T2.A
WHERE
    EXISTS (SELECT * FROM #V AS T2 WHERE T1.A = T2.A)

Outputnya adalah "3": tabel T dan U memiliki 2 dan 3 persamaan, tetapi WHEREpredikat selanjutnya menyaring baris yang dikembalikan ke 3, dan 2 tidak ada di V.

pembunuh bayaran
sumber