Выберите DISTINCT, возвращая слишком много записей

У меня есть две таблицы: продукты и предметы. Я хочу выбрать 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 ответа

Решение

Правильный запрос 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

Здесь нет distinct() функция в SQL. Ваш запрос анализируется как

SELECT DISTINCT (items.condition), ...

что эквивалентно

SELECT DISTINCT items.condition, ...

DISTINCT применяется ко всей строке - если две или более строки имеют одинаковые значения поля, ТО "дублирующаяся" строка удаляется из результирующего набора.

Вы, вероятно, хотите что-то более похожее

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

Я хочу выбрать отдельные товары, которые принадлежат продукту, на основе столбца условий, отсортированного по цене. 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_id а также product_id вместо.

Более подробная информация, ссылки и тест в этом ответе:
Выберите первую строку в каждой группе GROUP BY?

Используйте SELECT GROUP BY, извлекая только МИНУТУ (цену) для каждого ИЗДЕЛИЯ / СОСТОЯНИЯ.

Другие вопросы по тегам