Postgresql 为什么我必须向group by子句提供items.id列?
我想根据Postgresql 为什么我必须向group by子句提供items.id列?,postgresql,Postgresql,我想根据条件返回唯一的项目,按价格asc排序。我的查询失败,因为Postgres希望items.id出现在GROUPBY子句中。如果包含它,查询将返回与where子句匹配的所有内容,这不是我想要的。为什么我需要包含该列 select items.* from items where product_id = 1 and items.status = 'in_stock' group by condition /* , items.id returns everything */ order by
条件
返回唯一的项目,按价格asc
排序。我的查询失败,因为Postgres希望items.id
出现在GROUPBY
子句中。如果包含它,查询将返回与where
子句匹配的所有内容,这不是我想要的。为什么我需要包含该列
select items.*
from items
where product_id = 1 and items.status = 'in_stock'
group by condition /* , items.id returns everything */
order by items.price asc
| id | condition | price |
--------------------------
| 1 | new | 9 |
| 2 | good | 5 |
| 3 | good | 3 |
我只想要ID为1和3的项目
更新:这里有一个小提琴使用下面的答案,这仍然会产生错误:
问题在于PostgreSQL无法知道要从哪些
项中获取值;也就是说,它不能告诉你想要这个:
| id | condition | price |
--------------------------
| 1 | new | 9 |
| 3 | good | 3 |
而不是这个:
| id | condition | price |
--------------------------
| 1 | new | 9 |
| 2 | good | 5 |
要解决此问题,您需要使用某种聚合函数,例如MAX
:
SELECT MAX(id) AS id,
condition,
MAX(price) AS price
FROM items
WHERE product_id = 1
AND status = 'in_stock'
GROUP BY condition
ORDER BY price ASC
其中:
| id | condition | price |
--------------------------
| 1 | new | 9 |
| 3 | good | 5 |
(此限制是SQL标准的一部分,大多数DBMS都强制执行此限制。MySQL是一个例外,它允许您进行查询,但需要注意的是“服务器可以从每个组中自由选择任何值,因此,除非它们相同,否则所选值是不确定的”[]问题在于PostgreSQL无法知道要从哪些项中获取值;也就是说,它不能告诉你想要这个:
| id | condition | price |
--------------------------
| 1 | new | 9 |
| 3 | good | 3 |
而不是这个:
| id | condition | price |
--------------------------
| 1 | new | 9 |
| 2 | good | 5 |
要解决此问题,您需要使用某种聚合函数,例如MAX
:
SELECT MAX(id) AS id,
condition,
MAX(price) AS price
FROM items
WHERE product_id = 1
AND status = 'in_stock'
GROUP BY condition
ORDER BY price ASC
其中:
| id | condition | price |
--------------------------
| 1 | new | 9 |
| 3 | good | 5 |
(此限制是SQL标准的一部分,大多数DBMS都强制执行此限制。MySQL是一个例外,它允许您进行查询,但需要注意的是“服务器可以从每个组中自由选择任何值,因此,除非它们相同,否则所选值是不确定的”[]。
SQL标准要求这种行为,尽管有些数据库(如MySQL)会忽略它,而是返回不可预测的结果
如果“cond=good”有多行,您需要“cond=good”所在行的“id”,那么数据库应该给您哪一行?id=3或id=2的行?它怎么知道该选哪一个,但这是标准不允许的
在您的情况下,您似乎希望为每个条件选择最低价格行
PostgreSQL提供了一个扩展名,DISTINCT ON…
,以帮助实现这一点。Clodaldo在他的回答中已经证明了这一点,所以我在此不再重复。在
上使用DISTINCT将比下面的示例更有效
SQL的标准方法是使用一个窗口对结果进行排序,然后对排序后的数据进行过滤。不幸的是,这是非常低效的,因为它需要收集和排序与内部where子句匹配的所有行
SELECT *
FROM (
SELECT *, dense_rank() OVER w AS itemrank
FROM items
WHERE product_id = 1 AND items.status = 'in_stock'
WINDOW w AS (PARTITION BY cond ORDER BY price ASC)
) ranked_items
WHERE itemrank = 1;
()
另一种SQL标准方法是使用聚合子查询查找每个类别的最低价格,然后显示具有最低价格的所有行:
SELECT *
FROM items INNER JOIN (
SELECT cond, min(price) AS minprice
FROM items
WHERE product_id = 1 AND items.status = 'in_stock'
GROUP BY cond
) minprices(cond, price)
ON (items.price = minprices.price AND items.cond = minprices.cond)
ORDER BY items.price;
但是,与
版本上的不同,如果最低价格的商品有多个具有相同条件和价格的条目,则会显示多个条目
所以。。您应该真正使用DISTINCT ON方法,但您需要理解它。开始
另一方面,较新的PostgreSQL版本允许您引用表中的任何列,这些列的主键已在GROUP BY
中列出;它们标识主键上其他列的函数依赖关系。因此,如果您在较新版本中提到了PK,则不必聚合其他COL。这正是标准所要求的,但较旧的版本没有足够的智能来理解它,并且要求所有列都要显式列出
这是问这个问题的人通常想知道的,但并不严格适用于你的问题,因为你试图使用groupby
来过滤行。SQL标准要求这种行为,尽管像MySQL这样的一些数据库忽略它,反而返回不可预测的结果
如果“cond=good”有多行,您需要“cond=good”所在行的“id”,那么数据库应该给您哪一行?id=3或id=2的行?它怎么知道该选哪一个,但这是标准不允许的
在您的情况下,您似乎希望为每个条件选择最低价格行
PostgreSQL提供了一个扩展名,DISTINCT ON…
,以帮助实现这一点。Clodaldo在他的回答中已经证明了这一点,所以我在此不再重复。在
上使用DISTINCT将比下面的示例更有效
SQL的标准方法是使用一个窗口对结果进行排序,然后对排序后的数据进行过滤。不幸的是,这是非常低效的,因为它需要收集和排序与内部where子句匹配的所有行
SELECT *
FROM (
SELECT *, dense_rank() OVER w AS itemrank
FROM items
WHERE product_id = 1 AND items.status = 'in_stock'
WINDOW w AS (PARTITION BY cond ORDER BY price ASC)
) ranked_items
WHERE itemrank = 1;
()
另一种SQL标准方法是使用聚合子查询查找每个类别的最低价格,然后显示具有最低价格的所有行:
SELECT *
FROM items INNER JOIN (
SELECT cond, min(price) AS minprice
FROM items
WHERE product_id = 1 AND items.status = 'in_stock'
GROUP BY cond
) minprices(cond, price)
ON (items.price = minprices.price AND items.cond = minprices.cond)
ORDER BY items.price;
但是,与
版本上的不同,如果最低价格的商品有多个具有相同条件和价格的条目,则会显示多个条目
所以。。您应该真正使用DISTINCT ON方法,但您需要理解它。开始
另一方面,较新的PostgreSQL版本允许您引用表中的任何列,这些列的主键已在GROUP BY
中列出;它们标识主键上其他列的函数依赖关系。因此,如果您在较新版本中提到了PK,则不必聚合其他COL。这正是标准所要求的,但较旧的版本没有足够的智能来理解它,并且要求所有列都要显式列出
这是问这个问题的人通常想知道的,但并不严格适用于你的问题,因为你试图使用GROUP BY
来过滤行。这仍然会产生相同的错误。这里有一个提琴:-我将条件
更改为条件
,因为它是在SQL提琴中保留的。@de