选择DISTINCT返回太多记录

时间:2013-07-08 14:43:07

标签: sql postgresql distinct greatest-n-per-group distinct-on

我有两个表:产品和项目。我想根据distinct列选择属于产品的condition项,按price ASC排序。

+-------------------+
| id | name         |
+-------------------+
| 1 | Mickey Mouse  |
+-------------------+

+-------------------------------------+
| id | product_id | condition | price |
+-------------------------------------+
| 1  | 1           | New       | 90   |
| 2  | 1           | New       | 80   |
| 3  | 1           | Excellent | 60   |
| 4  | 1           | Excellent | 50   |
| 5  | 1           | Used      | 30   |
| 6  | 1           | Used      | 20   |
+-------------------------------------+

期望的输出:

+----------------------------------------+
| id | name          | condition | price |
+----------------------------------------+
| 2  | Mickey Mouse  | New       | 80    |
| 4  | Mickey Mouse  | Excellent | 50    |
| 6  | Mickey Mouse  | Used      | 20    |
+----------------------------------------+

这是查询。它返回六个记录而不是所需的三个记录:

SELECT DISTINCT(items.condition), items.price, products.name
FROM products
INNER JOIN items ON products.id = items.product_id
WHERE products.id = 1
ORDER BY items."price" ASC, products.name;

4 个答案:

答案 0 :(得分:3)

SQL中没有distinct()函数。您的查询正在被解析为

SELECT DISTINCT (items.condition), ...

相当于

SELECT DISTINCT items.condition, ...

DISTINCT适用于整行 - 如果两行或多行都具有相同的字段值,则从结果集中删除“重复”行。

你可能想要更像

的东西
SELECT items.condition, MIN(items.price), products.name
FROM ...
...
GROUP BY products.id

答案 1 :(得分:3)

更正PostgreSQL查询:

SELECT DISTINCT ON (items.condition) items.id, items.condition, items.price, products.name
FROM products
INNER JOIN items ON products.id = items.product_id
WHERE products.id = 1
ORDER BY items.condition, items.price, products.name;
  

SELECT DISTINCT ON(表达式[,...])仅保留第一行   给定表达式求值等于的每组行。

详情here

答案 2 :(得分:2)

  

我想根据商品选择属于产品的不同商品   条件列,按价格ASC排序。

您最有可能想要DISTINCT ON

SELECT *
FROM  (
   SELECT DISTINCT ON (i.condition)
          i.id AS item_id, p.name, i.condition, i.price
   FROM   products p
   JOIN   items    i ON i.products.id = p.id
   WHERE  p.id = 1
   ORDER  BY i.condition, i.price ASC
   )   sub
ORDER  BY item_id;

由于ORDER BY的前导列必须与DISTINCT ON中使用的列匹配,因此您需要一个子查询来获取您显示的排序顺序。

更好:

SELECT i.item_id, p.name, i.condition, i.price
FROM  (
   SELECT DISTINCT ON (condition)
          id AS item_id, product_id, condition, price
   FROM   items
   WHERE  product_id = 1
   ORDER  BY condition, price
   )   i
JOIN   products p ON p.id = i.product_id
ORDER  BY item_id;

应该快一点。

除此之外:您不应该使用非描述性名称id作为标识符。请改用item_idproduct_id

此相关答案中的更多细节,链接和基准测试:
Select first row in each GROUP BY group?

答案 3 :(得分:0)

使用SELECT GROUP BY,仅为每个产品/条件提取MIN(价格)。