Tại sao các ký tự đại diện trong các câu lệnh GROUP BY không hoạt động?


29

Tôi đang cố gắng để làm cho câu lệnh SQL sau hoạt động, nhưng tôi gặp lỗi cú pháp:

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

Ở đây, A là một bảng rộng có 40 cột và tôi muốn tránh liệt kê từng tên cột trong mệnh đề GROUP BY nếu có thể. Tôi có nhiều bảng như vậy mà tôi phải chạy một truy vấn tương tự, vì vậy tôi sẽ phải viết một Thủ tục lưu trữ. Cách tốt nhất để tiếp cận điều này là gì?

Tôi đang sử dụng MS SQL Server 2008.

Câu trả lời:


32

GROUP BY A.* không được phép trong SQL.

Bạn có thể bỏ qua điều này bằng cách sử dụng truy vấn con nơi bạn nhóm theo và sau đó tham gia:

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 ;

Có một tính năng trong tiêu chuẩn SQL-2003 để cho phép trong SELECTdanh sách, các cột không có trong GROUP BYdanh sách, miễn là chúng phụ thuộc chức năng vào chúng. Nếu tính năng đó đã được triển khai trong SQL-Server, truy vấn của bạn có thể đã được viết là:

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

Thật không may, tính năng này chưa được triển khai, ngay cả trong phiên bản SQL-Server 2012 - và không có trong bất kỳ DBMS nào khác như tôi biết. Ngoại trừ MySQL có nó nhưng không đầy đủ (không đầy đủ như: truy vấn trên sẽ hoạt động nhưng công cụ sẽ không kiểm tra sự phụ thuộc chức năng và các truy vấn không bằng văn bản khác sẽ hiển thị kết quả bán ngẫu nhiên sai).

Như @Mark Byers đã thông báo cho chúng tôi trong một bình luận, PostgreSQL 9.1 đã thêm một tính năng mới được thiết kế cho mục đích này. Nó hạn chế hơn so với triển khai của MySQL.


Bạn có thể đề cập đến một vài RDBMS thực hiện phần đó của tiêu chuẩn như được viết không? Ví dụ, tôi biết rằng MySQL sẽ cho phép bạn (được cung cấp các cài đặt phù hợp) để bao gồm các mục không nằm trong GROUP BYmệnh đề trong SELECTdanh sách, nhưng nó không được xác định là hàng đó sẽ xuất phát từ đâu (vì vậy nếu cột hoặc biểu thức không xuất hiện 't chức năng phụ thuộc vào biểu thức nhóm, sau đó nó có thể đến từ bất kỳ hàng trong nhóm).
Adam Robinson

@Adam: Không, tôi không biết RDBMS đã triển khai. MySQL có nó nhưng không đầy đủ, như nhận xét của bạn nói.
ypercubeᵀᴹ

Gotcha. Tôi thực sự đã hỏi liệu có, vì tôi có kinh nghiệm với RDBMS ít hơn nhiều so với tôi tưởng tượng hầu hết những người trả lời câu hỏi trên trang web này sẽ có;) Nhưng đó là sự nghi ngờ của tôi.
Adam Robinson

3
"và không có trong bất kỳ DBMS nào khác như tôi biết." PostgreQuery 9.1 đã thêm một tính năng mới được thiết kế cho mục đích này. Nó hạn chế hơn so với triển khai của MySQL.
Mark Byers

@MarkByer: thnx, tôi không biết điều đó.
ypercubeᵀᴹ

24

Ngoài cách giải quyết của @ ypercube, "gõ" không bao giờ là lý do để sử dụng SELECT *. Tôi đã viết về điều này ở đây và ngay cả với cách giải quyết tôi nghĩ rằng SELECTdanh sách của bạn vẫn nên bao gồm các tên cột - ngay cả khi có một số lượng lớn như 40.

Tóm lại, bạn có thể tránh nhập các danh sách lớn này bằng cách nhấp và kéo nút Cột cho đối tượng trong Object Explorer vào cửa sổ truy vấn của bạn. Ảnh chụp màn hình hiển thị chế độ xem nhưng điều tương tự có thể được thực hiện cho một bảng.

nhập mô tả hình ảnh ở đây

Nhưng nếu bạn muốn đọc về tất cả các lý do tại sao bạn phải chịu sự nỗ lực to lớn này của việc kéo một vật phẩm vài inch, xin vui lòng đọc bài viết của tôi . :-)


Trong PostgreSQL (với EMS SQL Manager), tôi thực hiện việc này xác định chế độ xem SELECT *và sau đó sao chép danh sách trường từ định nghĩa chế độ xem.
dezso

Tôi chắc chắn đồng ý rằng SELECT *không nên sử dụng. Tôi tò mò về GROUP BYtrường hợp mặc dù. @Aaron, có vấn đề hiệu quả với việc có 40 cột trong danh sách Nhóm theo không?
ypercubeᵀᴹ

1
@ypercube - Theo như tôi thấy nếu bạn nhóm theo A.PK, A.some, A.other, A.columnsnó thì không thực sự so sánh some, other, columnsđiều này chỉ là yêu cầu của cú pháp.
Martin Smith

1
@datagod xin lỗi, không, bất kỳ khoảng trống nào chỉ có thể được giải thích bởi nhóm nhà phát triển SSMS. :-)
Aaron Bertrand

1
@Pacerier Xin lỗi, tôi không đồng ý hoàn toàn , nhưng có lẽ bạn có thể giải thích.
Aaron Bertrand
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.