SQL Spec ต้องการ GROUP BY ใน EXISTS () หรือไม่


11

Microsoft อนุญาตให้ใช้ไวยากรณ์นี้ในขณะนี้

SELECT *
FROM ( VALUES (1) ) AS g(x)
WHERE EXISTS (
  SELECT *
  FROM ( VALUES (1),(1) )
    AS t(x)
  WHERE g.x = t.x
  HAVING count(*) > 1
);

ขอให้สังเกตว่าไม่มีGROUP BYในEXISTSข้อเป็น ANSI SQL ที่ถูกต้อง หรือเป็นเพียงการเปิดเผยรายละเอียดการปฏิบัติ

สำหรับการอ้างอิงไวยากรณ์เดียวกันนี้ไม่ได้รับอนุญาตใน PostgreSQL

ข้อผิดพลาด: คอลัมน์ "tx" จะต้องปรากฏในกลุ่มตามข้อหรือจะใช้ในฟังก์ชั่นรวม

แต่ไวยากรณ์นี้ได้รับอนุญาต ..

SELECT *
FROM ( VALUES (1) ) AS g(x)
WHERE EXISTS (
  SELECT 1  -- This changed from the first query
  FROM ( VALUES (1),(1) )
    AS t(x)
  WHERE g.x = t.x
  HAVING count(*) > 1
);

และไวยากรณ์นี้ได้รับอนุญาต

SELECT *
FROM ( VALUES (1) ) AS g(x)
WHERE EXISTS (
  SELECT *
  FROM ( VALUES (1),(1) )
    AS t(x)
  WHERE g.x = t.x
  GROUP BY t.x  -- This changed from the first query
  HAVING count(*) > 1
);

คำถามเกิดขึ้นจากการสนทนากับ @ErikE ในการแชท

คำตอบ:


11

ฉันพบมันในข้อมูลจำเพาะ SQL 2011 ...

ถ้า<select list>“*” ที่มีอยู่เพียงแค่ใน<table subquery>ที่มีอยู่ได้ทันทีใน<exists predicate>นั้น<select list>เทียบเท่ากับที่เป็นพล<value expression><literal>

สิ่งนี้เป็นการยืนยันว่าโดย*ไม่เท่ากับตัวอักษรตามอำเภอใจในบริบทนี้ว่าอันที่จริงแล้ว PostgreSQL นั้นทำลายข้อมูลจำเพาะ

โปรดทราบว่านี่เป็นปัญหาที่แตกต่างจาก

SELECT *
FROM ( VALUES (1),(2),(3) ) AS t(x)
HAVING count(*) > 1

ซึ่งฐานข้อมูลทั้งสองปฏิเสธ

PostgreSQL,

ข้อผิดพลาด: คอลัมน์ "tx" จะต้องปรากฏในกลุ่มตามข้อหรือจะใช้ในฟังก์ชั่นรวม

เซิร์ฟเวอร์ SQL

คอลัมน์ 'tx' ไม่ถูกต้องในรายการที่เลือกเนื่องจากมันไม่ได้อยู่ในฟังก์ชั่นรวมหรือประโยค GROUP BY

ทำไมข้อผิดพลาดนี้ยังคงอยู่ใน PostgreSQL

ขอบคุณไปที่ RhodiumToad บน irc.freenode.net/#PostgreSQL สำหรับความช่วยเหลือของเขาในการแก้ไขปัญหานี้ เขายังชี้ให้เห็นถึงความยากลำบากในการแก้ไขสถานการณ์นี้

20:33 <RhodiumToad> ปัญหาหนึ่งคือใน pg คุณสามารถมีอยู่ได้ (select func () จาก ... โดยที่ func () คือ SRF ที่อาจส่งคืน 0 แถว

SRF เป็นฟังก์ชันที่ส่งคืนชุด

ใน PostgreSQL เราสามารถทำได้เช่นใช้ SRF เพื่อสร้างซีรีย์ 1-10 ( generate_seriesอยู่ในแกน)

SELECT * FROM generate_series(1,10); 

และเราก็สามารถใส่มันตรงนี้ได้

SELECT generate_series(1,10);

สองของพวกเขาร่วมกันให้เราเข้าร่วมข้าม (ผลิตภัณฑ์คาร์ทีเซียน)

SELECT generate_series(1,10), generate_series(1,2);

แต่ถ้าหนึ่งใน 0 แถวเหล่านั้นกลับมาคุณจะไม่ได้อะไรเลย ..

SELECT * FROM ( VALUES (1) ) AS t(x)
CROSS JOIN ( SELECT 1 LIMIT 0 ) AS g;

และนั่นคือปัญหาที่เกิดจากการปรับให้เหมาะสมทั้งหมด คุณสามารถมี SRF ในรายการเลือกภายในของคำสั่ง EXIST ที่ส่งคืน 0 แถวและบังคับให้ EXISTS ประเมินค่าเป็นเท็จ

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