group by error:列“f.path”必须出现在group by子句中或在聚合函数中使用

c0vxltue  于 2021-07-24  发布在  Java
关注(0)|答案(4)|浏览(341)

在postgres 12中,我想表演一个 SELECTrecipes 只带一个图像(文件)的表。但是,在执行查询时 GROUP BY 我根据它的图像(文件)的数量得到重复的食谱。当试图使用 GROUP BY ,我得到以下错误:
列“f.path”必须出现在group by子句中,或在聚合函数中使用
我运行的查询是:

SELECT r.id, r.title, c.name AS chef_name, f.path
FROM recipes AS r
LEFT JOIN chefs AS c ON (r.chef_id = c.id)
LEFT JOIN recipe_files AS rf ON (rf.recipe_id = r.id)
LEFT JOIN files AS f ON (rf.file_id = f.id)
GROUP BY r.id, c.id
ORDER BY r.title ASC

如果我加上 f.pathGROUP BY ,我返回到最初的问题,即根据图像(文件)的数量接收包含重复项的列表。

zz2j4svz

zz2j4svz1#

如果每个配方只需要一个文件,则可以连接到只选择一个的派生表:

SELECT r.id, r.title, c.name AS chef_name, f1.path
FROM recipes AS r
  LEFT JOIN chefs AS c ON r.chef_id = c.id
  LEFT JOIN (
    SELECT DISTINCT ON (rf.recipe_id) rf.recipe_id, f.path
    FROM recipe_files AS rf 
      JOIN files AS f ON rf.file_id = f.id
    ORDER BY rf.recipe_id, f.id -- picks an arbitrary file
  ) f1 ON f1.recipe_id = r.id
ORDER BY r.title ASC
7gyucuyw

7gyucuyw2#

如果你想每个食谱一行,那么使用 distinct on :

SELECT DISTINCT ON (r.title, r.id) r.id, r.title, c.name AS chef_name, f.path
FROM recipes r LEFT JOIN chefs AS c ON (r.chef_id = c.id)
     recipe_files AS rf
     ON rf.recipe_id = r.id
     files f
     ON rf.file_id = f.id
ORDER BY r.title, r.id;
qmelpv7a

qmelpv7a3#

我对SQLServer比较熟悉,但是看起来postgres也有类似的功能。尝试使用行号()。可在此处找到参考资料:https://www.postgresqltutorial.com/postgresql-row_number/
会是这样的。你将需要修改它,以秩序如何你想。

SELECT 
    r.id
    , r.title
    , c.name AS chef_name
    , f.path
FROM (
    SELECT 
        r.id
        , r.title
        , c.name AS chef_name
        , f.path
        , ROW_NUMBER() OVER(PARTITION BY r.id, r.title, c.name AS chef_name, f.path ORDER BY r.title)
    FROM recipes AS r
        LEFT JOIN chefs AS c ON (r.chef_id = c.id)
        LEFT JOIN recipe_files AS rf ON (rf.recipe_id = r.id)
        LEFT JOIN files AS f ON (rf.file_id = f.id)
) 
WHERE row_number = 1;
wixjitnu

wixjitnu4#

尽早消除不需要的行。在这种情况下,应用 DISTINCT ON 加入之前 files :

SELECT r.id, r.title, c.name AS chef_name, f.path
FROM   recipes    r
LEFT   JOIN chefs c ON r.chef_id = c.id
LEFT   JOIN (
   SELECT DISTINCT ON (recipe_id)
          recipe_id, file_id
   FROM   recipe_files
   -- without ORDER BY it's truly arbitrary
   ) rf ON rf.recipe_id = r.id
LEFT   JOIN files f ON rf.file_id = f.id
ORDER  BY r.title;

关于 DISTINCT ON :
按组选择每组中的第一行?
当每个配方只有很少的文件时,查询应该是检索所有配方的最佳方法。
对于每个配方的许多文件,其他技术(要)更快:
按查询优化分组以检索每个用户的最新行
只检索很少的食谱,但其他技术(更多)更多efficient:. 比如:

SELECT r.id, r.title, c.name AS chef_name, f.path
FROM   recipes    r
LEFT   JOIN chefs c ON r.chef_id = c.id
LEFT   JOIN LATERAL (
   SELECT recipe_id, file_id
   FROM   recipe_files
   WHERE  recipe_id = r.id
   ORDER  BY recipe_id, file_id
   LIMIT  1
   ) rf ON true
LEFT   JOIN files f ON rf.file_id = f.id
WHERE  r.title = 'foo'                     -- some selective filter
ORDER  BY r.title;

请参见:
选择每个用户最后一条记录前一个月内的数据

相关问题