【问题标题】:Select DISTINCT returning too many records选择 DISTINCT 返回太多记录
【发布时间】:2013-07-08 14:43:07
【问题描述】:

我有两个表:Products 和 Items。我想根据condition 列选择属于产品的distinct 项目,按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;

【问题讨论】:

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


    【解决方案1】:

    正确的 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】:

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

      SELECT DISTINCT (items.condition), ...
      

      相当于

      SELECT DISTINCT items.condition, ...
      

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

      你可能想要更多类似的东西

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

      【讨论】:

      • Postgres 中有一个DISTINCT ON (...)“函数”。
      • 这很可能不是他想要的。 Postgres 提供DISTINCT ON。您的查询也无法返回items.id。像您建议的简单聚合函数 (min()) 无法返回所选行的其他列 - 而不是 DISTINCT ON
      【解决方案3】:

      我想根据 条件列,按价格排序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?

      【讨论】:

        【解决方案4】:

        使用 SELECT GROUP BY,只提取每个 PRODUCT/CONDITION 的 MIN(price)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-06-18
          • 1970-01-01
          • 2013-03-01
          • 2020-05-12
          • 1970-01-01
          • 2012-12-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多