使用子查询时,Postgres错误[列必须出现在GROUP BY子句中或在聚合函数中使用]


17

我有两个桌子employeephones。员工可以使用0到n个电话号码。我想列出员工姓名和他们的电话号码。我正在使用下面的查询运行正常。

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

在此处输入图片说明

员工表可能包含大量行。我一次只想获取一些员工。例如,我想获取3名员工的电话号码。我正在尝试运行此查询。

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

但是我得到这个错误。ERROR: column "employee.empname" must appear in the GROUP BY clause or be used in an aggregate function 两个查询之间的唯一区别是,我在后者中使用子查询来限制联接前的行。我该如何解决这个错误?

Answers:


21

Postgres能够与表的主键一起使用GROUP BY而无需在GROUP BY子句中添加该表的其他列的功能是相对较新的功能,仅适用于基表。优化器还不够聪明,无法识别视图,ctes或派生表的主键(如您的情况)。

您可以SELECTGROUP BY子句中添加所需的列:

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 ;

或使用子查询(并在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 ;

也可以写成:

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 ;

由于您的版本为9.3+。您还可以使用LATERAL联接:

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谢谢。这是一种简单干净的方法。
程序员,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.