SQL 带 having 子句的左连接

SQL Left join with having clause

所以我有这个 sql 代码:

select stone_number,stone_size,stone_shape,stone_weight 
from stone
left Join stone_price stp on stp.id_stone = stone.id_stone
group by stone_number,stone_size,stone_shape,stone_weight 
having  avg(stp.price) < stp.price;

Sqldeveloper returns:不是 group by 表达式,虽然我的代码中仍然有 group by。 我的目标是获得价格高于所有宝石平均价格的宝石物品。

select stone_number, stone_size, stone_shape, stone_weight 
from stone
left Join stone_price stp on stp.id_stone = stone.id_stone
group by stone_number, stone_size, stone_shape, stone_weight 
having (select avg(price) from stone_price) < max(stp.price)

您需要对 having 子句中的所有列使用聚合函数。因此,如果您想获得至少一个高于平均水平的奖品,您可以使用 max()。如果都需要更高,请使用 min().

一种方法是使用存储过程,您可以这样设置变量:

DECLARE @average_price INT
SET @average_price = (SELECT Avg(stone_price) from stone

然后在你的 SELECT 语句中

select stone_number,stone_size,stone_shape,stone_weight 
from stone
left Join stone_price stp on stp.id_stone = stone.id_stone
WHERE stone_price > @average_price

您可以使用 window 函数来做到这一点:

select *
from (
  select stone_number,stone_size,stone_shape,stone_weight, 
         stp.price, 
         avg(stp.price) over () as avg_price
  from stone
    left Join stone_price stp on stp.id_stone = stone.id_stone
)  
where price > avg_price;

请注意,外部联接的条件 table 实质上会将您的外部联接变成内部联接。如果您还想包括在 stone_price 中没有匹配的行,您需要

where price is null
   or price > avg_price;

否则,您只需将 left join 更改为 "plain" join


另一种选择是简单的子select:

select stone_number,stone_size,stone_shape,stone_weight, 
from stone
  left Join stone_price stp on stp.id_stone = stone.id_stone
where stp.price > (select avg(price) from stone_price);