นามแฝงของแบบสอบถามย่อยเหมือนกับนามแฝงข้อความค้นหาหลัก


23

ฉันมีแบบสอบถาม SQL ซึ่งมีชื่อแทนเหมือนกับนามแฝงของแบบสอบถามบางส่วน

ตัวอย่างเช่น:

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

วิธีนี้ใช้งานได้ดีเนื่องจากนามแฝงของแบบสอบถามย่อยดูเหมือนจะซ่อนตัวหลัก

  1. มันจะทำงานแบบนั้นในทุกกรณีหรือไม่?
  2. ฉันจะได้รับผลลัพธ์ที่ไม่ได้กำหนดหรือไม่?
  3. หากไม่เป็นเช่นนั้นฉันจะอ้างอิงถึงข้อความค้นหาหลักได้rอย่างไร

1
คำตอบสั้น ๆ คือ "1. ใช่", "2.No" และ "3. ในกรณีนี้คุณไม่สามารถ (ดังนั้นจึงไม่เป็นไรถ้าคุณต้องการอ้างอิงเช่นนี้)"
ypercubeᵀᴹ

คำตอบ:


15

ไม่เป็นไรสำหรับเคียวรีย่อยที่ซ้อนกันเพื่อใช้สมนามเดียวกันกับที่ใช้ในเคียวรีพาเรนต์แม้ว่าอาจจะสับสนเล็กน้อยสำหรับบางคนที่อ่านโค้ด พื้นที่ชื่อสำหรับนามแฝงในแบบสอบถามย่อยที่ซ้อนกันจะแยกออกจากพื้นที่ชื่อบนผู้ปกครอง ตัวอย่างเช่นแบบสอบถามด้านล่างมีแบบสอบถามย่อยแบบซ้อนbที่ยังมีชื่อแทนที่bใช้อยู่ สิ่งนี้อาจสร้างความสับสนให้โปรแกรมเมอร์ แต่ใช้ได้กับเอ็นจิน 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

ในเคียวรี่ย่อยที่สัมพันธ์กันคุณสามารถเข้าถึงนามแฝงของพาเรนต์ได้ดังนั้นชื่อแทนนั้นจะต้องไม่ซ้ำกันในเคียวรีพาเรนต์และเคียวรีย่อยที่สัมพันธ์กัน หากเราใช้แบบสอบถามย่อยที่มีความสัมพันธ์เช่นที่อยู่ด้านล่างเรามีพื้นที่ชื่อเดียวทั่วโลกที่ใช้ร่วมกันระหว่างแบบสอบถามหลักและแบบสอบถามย่อยที่เกี่ยวข้อง:

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)

ข้อความค้นหาย่อยที่มีความสัมพันธ์ไม่ได้มีนามแฝงที่มันไม่ได้มีส่วนร่วมในการเข้าร่วมเป็นเช่น1 การอ้างอิงbและb2สำหรับbarทั้งสองพร้อมใช้งานสำหรับเคียวรีย่อยที่เคียวรีย่อยที่สัมพันธ์กันแบ่งใช้เนมสเปซของพวกเขาสำหรับนามแฝงกับพาเรนต์


1โปรดทราบว่าเครื่องมือเพิ่มประสิทธิภาพอาจเลือกที่จะใช้ตัวดำเนินการเข้าร่วมภายในแผนเบื้องหลังแม้ว่าการดำเนินการจริงที่ระบุเป็นแบบสอบถามย่อยที่มีความสัมพันธ์กันและไม่ใช่การรวมกับแบบสอบถามย่อยซ้อน


ข้อความค้นหาย่อยในแบบสอบถามแรกเป็นตารางที่ได้รับมาและ SQL มาตรฐานกำหนดให้มีการตั้งชื่อเสมอ: ไม่มีเหตุผลเชิงตรรกะสำหรับความต้องการนี้ แต่ SQL Server ได้นำไปใช้แล้วอย่างไรก็ตามในตัวอย่างเฉพาะที่คุณเลือกชื่อแน่นอน จำเป็นต้องใช้ เคียวรีย่อยในเคียวรีที่สองไม่ใช่ตารางที่ได้รับดังนั้นทำไมจึงไม่ต้องการชื่อ (ความจริงมันเป็นเคียวรีย่อยที่สัมพันธ์กันเป็นสาระสำคัญ)
oneday เมื่อ

@onedaywhen - ฉันไม่สามารถนึกถึงสถานการณ์ใด ๆ ได้ แต่เป็นคิวรีย่อยที่มีความสัมพันธ์กันซึ่งคิวย่อยนั้นต้องการเข้าถึงนามแฝงที่ใช้ในพาเรนต์ คุณมีบางอย่างที่เฉพาะเจาะจงในใจ?
เกี่ยวข้องกับ OfTunbridgeWells เมื่อ

ฉันไม่แน่ใจว่าฉันเข้าใจคำถามของคุณ บางทีฉันควรทำให้ชัดเจนว่าฉันตอบกลับความคิดเห็นของคุณโดยเฉพาะ "แบบสอบถามย่อยที่สัมพันธ์กันไม่มีนามแฝงเนื่องจากไม่มีส่วนร่วมในการเข้าร่วมเช่นนี้" การตอบสนองของฉันควรจะบอกจุดที่กฎเกี่ยวกับตัวแปรช่วง (สิ่งที่ SQL ชื่อสายสัมพันธ์ 'และคุณเรียกว่า' นามแฝง ') มาตรฐาน SQL จะไม่เกี่ยวข้องโดยตรงกับการมีส่วนร่วมของพวกเขา (หรืออื่น ๆ ) ในการเข้าร่วม
oneday เมื่อ

ตัวอย่างง่าย ๆ : SELECT * FROM ( SELECT c FROM T ) AS T2;- ไม่มีการรวมไม่มีความสัมพันธ์ แต่มาตรฐาน SQL ต้องการให้ตารางที่ได้รับถูกกำหนดตัวแปรช่วง ( T2ในกรณีนี้)
oneday เมื่อ

3

ConcernedOfTunbridgeWells คุณเขียน (เน้นที่เหมือง): "ในเคียวรีย่อยที่สัมพันธ์กันคุณสามารถเข้าถึงนามแฝงของพาเรนต์ดังนั้นชื่อแทนจะต้องไม่ซ้ำกันในเคียวรีหลักและเคียวรีย่อยที่สัมพันธ์กัน"

ฉันไม่เชื่อว่าเป็นสิ่งจำเป็น ฉันเชื่อว่าหากนามแฝงถูกใช้ในเคียวรีย่อยที่สัมพันธ์กันเป็นชื่อสหสัมพันธ์เช่นเดียวกับ alias ของตารางในเคียวรีภายนอก, alias ในเคียวรีย่อยจะมีความสำคัญกว่า

ตัวอย่าง:

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)

เอาต์พุตคือ "3": ตาราง T และ U มี 2 และ 3 ที่เหมือนกัน แต่เพรดิเคตWHEREจะกรองแถวที่ส่งคืนไปยัง 3 เพิ่มเติมและ 2 ไม่มีอยู่ใน V

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.