Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 为什么我必须向group by子句提供items.id列?_Postgresql - Fatal编程技术网

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