2016-08-31 7 views
0

У меня есть таблица продуктов, которая содержит все продукты, которые могут быть проданы продавцом. Он имеет два столбца в качестве первичного ключа; product_code и amount (товар масса в основном).Ограничения по группе по

Поскольку вес продукта варьируется, их цена варьируется. Доступны 6 типов веса продукта: 0.5, 1, 1.5, 2, 2.5, 3. Код продукта для продукта с разным весом будет таким же.

Образец данных:

product_code | product_quantity | amount | quantity 
1234   | 6    | 0.5kg | 0 
1234   | 6    | 1.0kg | 7 
1234   | 6    | 1.5kg | 8 

Я хочу, чтобы отобразить все продукты, но только один раз в PRODUCT_CODE.

SELECT * FROM products where group by product_code 

Учитывая указанные три строки, этот запрос дает мне первую строку из трех.

Однако я хочу вернуть строки с количеством больше нуля, если они существуют, иначе любая строка будет делать.

Какую модификацию необходимо внести в моем запросе для достижения этой цели?

Вот моя структура таблицы:

Table structure

+1

Вы пишете: «Это имеет два столбца в качестве первичного ключа: product_code и product_weight ". Бит на изображении я вижу ключевой символ на 'product_code' и' amount'. –

+0

@PaulSpiegel извините за это, только что обновил мой вопрос. –

ответ

0

Принимая во внимание, что вы используете нестандартную функцию, т.е. группировка по подмножеству необобщенных столбцов, в этом случае (не гарантируется) первая строка возвращается для каждой группы ...

ли группу более чем упорядоченный набор строк, который сталкивается ненулевые величины до того нулевых величин:

SELECT * FROM (
    SELECT * FROM products 
    ORDER BY quantity desc 
) x 
GROUP BY product_code 

Примечание. Реализация, которую вы используете, ведет себя таким образом, но не даются гарантии, что будущие версии будут продолжать надежно работать так, как вы хотите.

Кроме того, в соответствии с documentation:

С MySQL 5.7.5, то режим SQL по умолчанию включает в себя ONLY_FULL_GROUP_BY.

Это значит, что ваш запрос не будет работать на 5.7.5+, если вы не отключите ONLY_FULL_GROUP_BY после установки.

Надежный и портативный способ заключается в использовании подзапроса, который находит все необходимые количества и присоединяется к нему. Но у вас есть дополнительное усложнение, что количество не является уникальным для продукта, так что вы должны разорвать связь, используя сумму:

SELECT p.* 
FROM products p 
JOIN (SELECT p2.product_code, max_quantity, max(amount) max_amount 
     FROM products p2 
     JOIN (SELECT product_code, MAX(quantity) max_quantity 
      FROM products 
      GROUP BY product_code) q 
     ON q.product_code = p2.product_code 
     AND max_quantity = p2.quantity 
     GROUP BY product_code, max_quantity) qa 
    ON p.product_code = qa.product_code 
    AND quantity = max_quantity 
    AND amount = max_amount 

Первый подзапрос находит максимальное количество (что данные, которые вы хотите), то следующий подзапрос находит максимальное количество всех строк с таким максимальным количеством (может быть более одной строки, разделяющей максимальную сумму). Поскольку комбинация кода продукта, количества и количества уникальна, присоединяется к таблице, используя эти значения, чтобы дать вам нужные строки.

Отказ от ответственности: Код не может скомпилировать или работать, как это было просмотрел в на моем телефоне (но есть разумный шанс, что он будет работать)

+0

Большое спасибо, это сработало. –

+0

wou; lld вы объяснили мне, что x внутри запроса? –

+1

@ BOTJr. «X», который может быть чем угодно, необходим синтаксису, который требует, чтобы всем подзапросам был присвоен псевдоним (даже если он фактически не используется). Если это сделает код более четким, вы можете сделать его именем, например «ordered_by_quantity» или что-то еще. Но я всегда просто использую «х» (по какой-то особой причине, кроме имени переменной по умолчанию в алгебре). – Bohemian

1

Если вы хотите одну строку для каждого product_code с наивысшим quantity вы может использовать условие WHERE с коррелированным подзапросом, который сортируется по quantity и ограничивается одной строкой.

SELECT p1.* 
FROM products p1 
WHERE (p1.product_code, p1.amount) = (
    SELECT p2.product_code, p2.amount 
    FROM products p2 
    WHERE p2.product_code = p1.product_code 
    ORDER BY p2.quantity DESC 
    LIMIT 1 
) 

Для этого необходимо использовать первичный ключ. Но поскольку мы имеем WHERE p2.product_code = p1.product_code в подзапроса, мы можем переписать его:

SELECT p1.* 
FROM products p1 
WHERE p1.amount = (
    SELECT p2.amount 
    FROM products p2 
    WHERE p2.product_code = p1.product_code 
    ORDER BY p2.quantity DESC 
    LIMIT 1 
) 

Теперь MySQL должен иметь возможность кэшировать подзапрос результат для каждого product_code. С индексом на (product_code, quantity, amount) или просто (product_code, quantity) подзапрос должен выполняться довольно быстро.

Чтобы сохранить результат детерминированным, вы можете расширить предложение ORDER BY подзапроса. Если две строки с одинаковыми product_code имеют один и тот же quantity и вы хотите, чтобы выбрать один с большим amount (которые можите быть равны, так как она является частью первичного ключа), затем используйте

ORDER BY p2.quantity DESC, p2.amount DESC 
Смежные вопросы