缘起
每个月抓取电商平台某几个类目的商品概要数据。snapshots
数据表保存不同类目在不同时间的快照列表,一对多,连接 snapshot_products
数据表,可获取一个类目快照下的商品数。
SQL初始版本:
SELECT
snpt.url 快照地址
,snpt.title 快照标题
,snpt.id 快照ID
,count(prodx.id) 快照商品数
,to_char(snpt.created_at, 'yyyy-MM-dd') as 快照时间
from snapshots snpt
join snapshot_products prodx on prodx.snapshot_id = snpt.id
where snpt.site_id = 1573251441454223360
and snpt.created_at > '2023-01-01'
group by 快照地址
;
报错:
ERROR: column "snpt.title" must appear in the GROUP BY clause or be used in an aggregate function
原因
在SQL3(1999)之前,所选字段必须出现在GROUP BY子句[*]中。
聚合查询时,SELECT子句中可以有3种内容:
- 在GROUP BY子句中出现的列名
- 使用聚合函数(SUM、MAX、AVG等)
- 常量
注:MySQL数据库是支持聚合后在SELECT使用原表的列,但最好养成习惯,不要去用。
可以在子查询中计算聚合,然后将其自身与之合并以获得需要显示的其他列.网上示例代码如下:
SELECT m.cname, m.wmname, t.mx
FROM (
SELECT cname, MAX(avg) AS mx
FROM makerar
GROUP BY cname
) t JOIN makerar m ON m.cname = t.cname AND t.mx = m.avg
;
还可以使用 窗口函数
,看起来更简单:
SELECT cname, wmname, MAX(avg) OVER (PARTITION BY cname) AS mx
FROM makerar
;
解决
根据提示,把 GROUP BY
子句后面的字段补全即可。
SELECT
snpt.url 快照地址
,snpt.title 快照标题
,snpt.id 快照ID
,count(prodx.id) 快照商品数
,to_char(snpt.created_at, 'yyyy-MM-dd') as 快照时间
from snapshots snpt
join snapshot_products prodx on prodx.snapshot_id = snpt.id
where snpt.site_id = 1573251441454223360
and snpt.created_at > '2023-01-01'
group by 快照地址, 快照标题, 快照ID
;
测试发现,GROUP BY
后直接使用 快照ID
字段也行。因为该字段是唯一主键:
group by 快照ID
关于sql:必须出现在GROUP BY子句中或在聚合函数中使用 https://www.codenong.com/19601948/
SQL报错 | column "t1.col_1" must appear in the GROUP BY clause or be used in an aggregate function https://zhuanlan.zhihu.com/p/457341706