Lỗi postgres [cột phải xuất hiện trong mệnh đề GROUP BY hoặc được sử dụng trong hàm tổng hợp] khi sử dụng truy vấn phụ


15

Tôi có hai bảng employeephones. Một nhân viên có thể có 0 đến n số điện thoại. Tôi muốn liệt kê tên nhân viên với số điện thoại của họ. Tôi đang sử dụng truy vấn dưới đây chạy tốt.

SELECT empname,array_agg(phonenumber) AS phonenumbers 
FROM employee LEFT OUTER JOIN phones ON employee.empid = phones.empid
GROUP BY employee.empid

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

Bảng nhân viên có thể chứa số lượng lớn các hàng. Tôi muốn chỉ lấy một số nhân viên tại một thời điểm. Ví dụ tôi muốn lấy 3 nhân viên bằng số điện thoại của họ. Tôi đang cố gắng để chạy truy vấn này.

SELECT empname,array_agg(phonenumber) AS phonenumbers 
FROM 
(SELECT * FROM employee ORDER BY empname LIMIT 3 OFFSET 0) AS employee 
LEFT OUTER JOIN phones ON employee.empid = phones.empid
GROUP BY employee.empid

Nhưng tôi nhận được lỗi này. ERROR: column "employee.empname" must appear in the GROUP BY clause or be used in an aggregate function Sự khác biệt duy nhất giữa hai truy vấn là tôi đang sử dụng truy vấn phụ ở sau để giới hạn các hàng trước khi tham gia. Làm thế nào để tôi giải quyết lỗi này?

Câu trả lời:


20

Tính năng của Postgres để có thể sử dụng khóa chính của bảng GROUP BYvà không cần thêm các cột khác của bảng đó trong GROUP BYmệnh đề tương đối mới và chỉ hoạt động cho các bảng cơ sở. Trình tối ưu hóa chưa đủ (chưa?) Đủ thông minh để xác định các khóa chính cho chế độ xem, byte hoặc bảng dẫn xuất (như trong trường hợp của bạn).

Bạn có thể thêm các cột bạn muốn SELECTvào GROUP BYmệnh đề:

SELECT e.empname, array_agg(p.phonenumber) AS phonenumbers 
FROM 
(SELECT * FROM employee ORDER BY empname LIMIT 3 OFFSET 0) AS e 
LEFT OUTER JOIN phones AS p ON e.empid = p.empid
GROUP BY e.empid, e.empname 
ORDER BY e.empname ;

hoặc sử dụng truy vấn con (và chuyển vào GROUP BYđó):

SELECT e.empname,
       (SELECT array_agg(p.phonenumber) 
        FROM phones AS p
        WHERE e.empid = p.empid
       ) AS phonenumbers 
FROM 
(SELECT * FROM employee ORDER BY empname LIMIT 3 OFFSET 0) AS e 
ORDER BY e.empname ;

cũng có thể được viết là:

SELECT e.empname,
       (SELECT array_agg(p.phonenumber) 
        FROM phones AS p
        WHERE e.empid = p.empid
       ) AS phonenumbers 
FROM employee AS e
ORDER BY e.empname LIMIT 3 OFFSET 0 ;

Vì bạn đang ở phiên bản 9.3+. bạn cũng có thể sử dụng một LATERALtham gia:

SELECT e.empname,
       p.phonenumbers 
FROM 
   (SELECT * FROM employee ORDER BY empname LIMIT 3 OFFSET 0) AS e
LEFT JOIN LATERAL
   (SELECT array_agg(phonenumber) AS phonenumbers
    FROM phones 
    WHERE e.empid = phones.empid
   ) AS p ON TRUE 
ORDER BY e.empname ;

@ypercude Cảm ơn. Đây là một cách đơn giản và sạch sẽ.
Lập trình viên
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.