You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用peewee实现多聚合查询:获取每个A对应x、y最小值关联的z值

问题原因

你之前的写法无法得到正确结果的核心原因是:同一个A记录对应的最小x值、最小y值大概率属于B表的不同行,直接在单次JOIN的分组查询中取B.z,数据库只会返回分组内任意一行的z值,所以会出现z_x和z_y值重复覆盖的问题。

原生SQL实现方案

提供两种通用实现,可根据你使用的数据库版本选择:

方案1:窗口函数实现(推荐,支持MySQL8.0+、PostgreSQL、SQLite 3.25+等新版本数据库)

SELECT 
    t2.id AS A_id,
    MIN(CASE WHEN rn_x = 1 THEN t1.x END) AS x,
    MIN(CASE WHEN rn_x = 1 THEN t1.z END) AS z_x,
    MIN(CASE WHEN rn_y = 1 THEN t1.y END) AS y,
    MIN(CASE WHEN rn_y = 1 THEN t1.z END) AS z_y
FROM A AS t2
INNER JOIN (
    SELECT 
        *,
        ROW_NUMBER() OVER (PARTITION BY A_key ORDER BY x ASC) AS rn_x,
        ROW_NUMBER() OVER (PARTITION BY A_key ORDER BY y ASC) AS rn_y
    FROM B
) AS t1 ON t1.A_key = t2.id
GROUP BY t2.id

实现逻辑:先对B表按关联的A_id分组,分别给每个分组内的记录按x、y升序排名,排名为1的就是对应列最小值所在的行,最后按A分组取出对应的值即可。

方案2:子查询关联实现(兼容旧版本不支持窗口函数的数据库)

SELECT
    t2.id AS A_id,
    tx.min_x AS x,
    tx.z AS z_x,
    ty.min_y AS y,
    ty.z AS z_y
FROM A AS t2
-- 关联获取x最小值对应的z
INNER JOIN (
    SELECT b1.A_key, b1.x AS min_x, b1.z 
    FROM B b1
    WHERE b1.x = (SELECT MIN(b2.x) FROM B b2 WHERE b2.A_key = b1.A_key)
) AS tx ON tx.A_key = t2.id
-- 关联获取y最小值对应的z
INNER JOIN (
    SELECT b1.A_key, b1.y AS min_y, b1.z 
    FROM B b1
    WHERE b1.y = (SELECT MIN(b2.y) FROM B b2 WHERE b2.A_key = b1.A_key)
) AS ty ON ty.A_key = t2.id

对应Peewee实现(以窗口函数方案为例)

from peewee import fn, Case

# 构造带排名的B表CTE子查询
B_ranked = B.select(
    B,
    fn.ROW_NUMBER().over(partition_by=[B.A_key], order_by=[B.x.asc()]).alias('rn_x'),
    fn.ROW_NUMBER().over(partition_by=[B.A_key], order_by=[B.y.asc()]).alias('rn_y')
).cte('B_ranked')

# 主查询
query = (A
         .select(
             A.id.alias('A_id'),
             fn.MIN(Case(None, [(B_ranked.c.rn_x == 1, B_ranked.c.x)])).alias('x'),
             fn.MIN(Case(None, [(B_ranked.c.rn_x == 1, B_ranked.c.z)])).alias('z_x'),
             fn.MIN(Case(None, [(B_ranked.c.rn_y == 1, B_ranked.c.y)])).alias('y'),
             fn.MIN(Case(None, [(B_ranked.c.rn_y == 1, B_ranked.c.z)])).alias('z_y')
         )
         .join(B_ranked, on=(B_ranked.c.A_key == A.id))
         .group_by(A.id)
         .with_cte(B_ranked))

内容的提问来源于stack exchange,提问作者gaspardbb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 01:36:03