SQL 标准需要这种行为,尽管像 MySQL 这样的一些数据库会忽略它,而是返回不可预测的结果。
如果“cond = good”有不止一行,并且您询问“cond = good”所在行的“id”,数据库应该给您哪一行?id = 3 或 id = 2 的行?它应该如何知道选择哪个?如果有多个候选者,MySQL 会选择任意行,但标准不允许这样做。
在您的情况下,您似乎想为每个条件选择最低价格行。
PostgreSQL 提供了一个扩展 ,DISTINCT ON ...
来帮助解决这个问题。Clodaldo 在他的回答中已经证明了这一点,所以我不会在这里重复。使用DISTINCT ON
将比下面的示例更有效。
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;
(http://sqlfiddle.com/#!1/33786/19)
另一种 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
,这将显示多个条目。
所以..你真的应该使用 DISTINCT ON 方法,但你需要理解它。从这里的 PostgreSQL 文档开始。
附带说明一下,较新的 PostgreSQL 版本允许您引用表的任何列,其主键已在GROUP BY
; 它们确定其他列对主键的功能依赖性。因此,如果您在较新版本中提到了 PK,则不必汇总其他列。这就是标准所要求的,但旧版本不够聪明,无法弄清楚并要求明确列出所有列。
这就是提出这个问题的人通常想知道的,但并不严格适用于您的问题,因为事实证明您正在尝试使用它GROUP BY
来过滤行。