ทำไมสัญลักษณ์ตัวแทนในกลุ่มจำแนกตามคำสั่งไม่ทำงาน


29

ฉันพยายามทำให้คำสั่ง SQL ต่อไปนี้ทำงาน แต่ฉันได้รับข้อผิดพลาดทางไวยากรณ์:

SELECT A.*, COUNT(B.foo)
FROM TABLE1 A
LEFT JOIN TABLE2 B ON A.PKey = B.FKey
GROUP BY A.*

ที่นี่ A เป็นตารางกว้างที่มี 40 คอลัมน์และฉันต้องการหลีกเลี่ยงการแสดงชื่อแต่ละคอลัมน์ในกลุ่มตามข้อถ้าเป็นไปได้ ฉันมีตารางดังกล่าวจำนวนมากซึ่งฉันต้องเรียกใช้แบบสอบถามที่คล้ายกันดังนั้นฉันจะต้องเขียนกระบวนงานที่เก็บไว้ วิธีที่ดีที่สุดในการเข้าถึงสิ่งนี้คืออะไร?

ฉันใช้ MS SQL Server 2008

คำตอบ:


32

GROUP BY A.* ไม่อนุญาตใน SQL

คุณสามารถข้ามสิ่งนี้ได้โดยใช้แบบสอบถามย่อยที่คุณจัดกลุ่มตามแล้วเข้าร่วม:

SELECT A.*, COALESCE(B.cnt, 0) AS Count_B_Foo
FROM TABLE1 AS A
  LEFT JOIN 
      ( SELECT FKey, COUNT(foo) AS cnt
        FROM TABLE2 
        GROUP BY FKey
      ) AS B 
    ON A.PKey = B.FKey ;

มีคุณสมบัติในมาตรฐาน SQL-2003 ที่จะอนุญาตในSELECTรายการคอลัมน์ที่ไม่ได้อยู่ในGROUP BYรายการตราบใดที่คุณลักษณะเหล่านั้นขึ้นอยู่กับหน้าที่ หากฟีเจอร์นั้นถูกนำไปใช้ใน SQL-Server เคียวรีของคุณอาจถูกเขียนเป็น:

SELECT A.*, COUNT(B.foo)
FROM TABLE1 A
LEFT JOIN TABLE2 B ON A.PKey = B.FKey
GROUP BY A.pk                          --- the Primary Key of table A

น่าเสียดายที่คุณลักษณะนี้ยังไม่ได้ใช้งานแม้จะอยู่ในรุ่น SQL-Server 2012 - และไม่ได้อยู่ใน DBMS อื่น ๆ เท่าที่ฉันรู้ ยกเว้น MySQL ที่มี แต่ไม่เพียงพอ (ไม่เพียงพอเป็น: แบบสอบถามด้านบนจะทำงานได้ แต่เครื่องยนต์จะไม่ตรวจสอบการพึ่งพาการทำงานและแบบสอบถามที่ไม่เป็นลายลักษณ์อักษรอื่น ๆ จะแสดงผลลัพธ์กึ่งสุ่มที่ไม่ถูกต้อง

ในฐานะที่เป็น@ Mark Byersแจ้งให้เราทราบในความคิดเห็นPostgreSQL 9.1 ได้เพิ่มคุณสมบัติใหม่ที่ออกแบบมาเพื่อวัตถุประสงค์นี้ มันมีข้อ จำกัด มากกว่าการใช้ MySQL


คุณช่วยพูดถึงสองสาม RDBMS ที่ใช้ส่วนของมาตรฐานที่เขียน? ฉันรู้ว่าตัวอย่างเช่น MySQL ที่จะช่วยให้คุณ (ที่ได้รับการตั้งค่าที่เหมาะสม) เพื่อรวมรายการที่ไม่ได้อยู่ในGROUP BYข้อในSELECTรายการ แต่ใบมันไม่ได้กำหนดเป็นที่แถวนั้นค่าจะมาจาก (ดังนั้นหากคอลัมน์หรือแสดงออกISN ไม่สามารถใช้งานได้กับการแสดงออกของการจัดกลุ่มจากนั้นอาจมาจากแถวใดก็ได้ในกลุ่ม)
Adam Robinson

@ อดัม: ไม่ฉันรู้ว่าไม่มี RDBMS ที่ใช้งานอยู่ MySQL มี แต่ไม่เพียงพอตามความคิดเห็นของคุณ
ypercubeᵀᴹ

Gotcha จริง ๆ แล้วฉันถามว่ามีหรือไม่เพราะฉันมีประสบการณ์กับ RDBMS น้อยกว่าที่ฉันคิดว่าคนส่วนใหญ่ที่ตอบคำถามในเว็บไซต์นี้จะมี;) แต่นั่นเป็นความสงสัยของฉัน
Adam Robinson

3
"และไม่ได้อยู่ใน DBMS อื่น ๆ เท่าที่ฉันรู้" PostgreSQL 9.1 ได้เพิ่มฟีเจอร์ใหม่ที่ออกแบบมาเพื่อจุดประสงค์นี้ มันมีข้อ จำกัด มากกว่าการใช้ MySQL
Mark Byers

@ MarkByers: ขอบคุณฉันไม่รู้
ypercubeᵀᴹ

24

นอกเหนือไปจาก @ ypercube ของวิธีแก้ปัญหา "พิมพ์" SELECT *ไม่เคยมีข้อแก้ตัวสำหรับการใช้ ฉันได้เขียนเกี่ยวกับที่นี่และแม้จะมีวิธีแก้ปัญหาฉันคิดว่าSELECTรายการของคุณยังควรรวมชื่อคอลัมน์ - แม้ว่าจะมีจำนวนมากเช่น 40

เรื่องย่อสั้น ๆ คุณสามารถหลีกเลี่ยงการพิมพ์รายการขนาดใหญ่เหล่านี้ได้ด้วยการคลิกและลากโหนดคอลัมน์สำหรับวัตถุใน Object Explorer ลงในหน้าต่างแบบสอบถามของคุณ ภาพหน้าจอแสดงมุมมอง แต่สามารถทำสิ่งเดียวกันสำหรับตารางได้

ป้อนคำอธิบายรูปภาพที่นี่

แต่ถ้าคุณต้องการที่จะอ่านเกี่ยวกับเหตุผลทั้งหมดว่าทำไมคุณควรเรื่องตัวเองให้อยู่ในระดับนี้มากของความพยายามของลากรายการไม่กี่นิ้ว, โปรดอ่านโพสต์ของฉัน :-)


ใน PostgreSQL (ด้วย EMS SQL Manager) ฉันทำสิ่งนี้เพื่อกำหนดมุมมองSELECT *แล้วคัดลอกรายการเขตข้อมูลจากคำจำกัดความมุมมอง
dezso

ฉันเห็นด้วยอย่างแน่นอนว่าSELECT *ไม่ควรใช้ ฉันสงสัยเกี่ยวกับGROUP BYกรณีนี้ @Aaron มีปัญหาเรื่องประสิทธิภาพหรือไม่เมื่อมี 40 คอลัมน์ในรายการ Group By
ypercubeᵀᴹ

1
@ypercube - เท่าที่ฉันเคยเห็นถ้าคุณจัดกลุ่มโดยA.PK, A.some, A.other, A.columnsไม่ต้องกังวลจริง ๆ แล้วการเปรียบเทียบ some, other, columnsนี่เป็นเพียงแค่ต้องการไวยากรณ์
Martin Smith

1
@datagod ขออภัยไม่ช่องว่างใด ๆ สามารถอธิบายได้โดยทีม dev SSMS :-)
Aaron Bertrand

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