#mysql
#mysql
Вопрос:
У меня есть следующий запрос MySQL:
SELECT *
FROM products
WHERE catalog = 1
GROUP BY style
ORDER BY name ASC
limit 0, 100
Поскольку у меня есть несколько продуктов с одинаковым «стилем», это вернет информацию о любом первом продукте, который имеет определенный «стиль» (через условие GROUP BY).
Поскольку на некоторые товары предоставляется «скидка», мой вопрос заключается в следующем: КАК мне сделать так, чтобы условие «ГРУППИРОВАТЬ ПО стилю» отдавало первый приоритет продукту со скидкой? Моя конечная цель — использовать 1 запрос вместо того, чтобы после этого просматривать каждый возвращенный стиль и проверять, есть ли какие-либо товары со скидкой
Если я укажу «ГРУППИРОВАТЬ ПО стилю, со скидкой», он вернет 2 продукта с одинаковым стилем: 1 со скидкой и 1 без скидки. Это НЕ то, что мне нужно — мне нужно вернуть только 1 соответствующий (уникальный) стиль, но отдать предпочтение тем товарам, которые соответствуют этому стилю и на которые предоставляется скидка.
Комментарии:
1. Что вы подразумеваете под «предпочтением»? Вам нужны только результаты со скидкой или вы хотите, чтобы сначала они были упорядочены по скидке, а затем остальные результаты?
2. @wes: Я хочу, чтобы результаты имели скидку, НО если скидки нет, я все равно хочу получать результаты.
3. если выходные данные для данного стиля [normal, discounted] возвращают только [со скидкой], но если это просто [normal] возвращает [normal]?
4. @Дэн: именно. не уверен, как поместить это в запрос.
5. вам нужен какой-либо товар со скидкой или товар с наибольшей скидкой?
Ответ №1:
Вы не можете наложить приоритет в пределах группового набора в одном запросе. Вы можете ограничить свои результаты, используя WHERE перед применением GROUP BY, но это просто лишит ваш результат строк, не удовлетворяющих условию WHERE. Чтобы найти порядок в сгруппированных наборах, используйте запрос, подобный этому: (предполагая, что id здесь является первичным ключом)
SELECT p.* FROM
( SELECT style,max(discount) as highest_discount
FROM products
WHERE catalog = 1
GROUP BY style ) p1
JOIN products p
ON p.id =
( SELECT pu.id
FROM products pu
WHERE pu.catalog = 1
AND pu.style = p1.style
AND pu.discount = p1.highest_discount
LIMIT 1 )
Комментарии:
1. Петр, это сработало как по волшебству. Однако для обработки запроса в моей системе потребовалось ~ 6 секунд (и 2,7 секунды на рабочем сервере), и это учитывая, что я ограничил его значением 0,12. В значительной степени это то же самое или медленнее, чем выполнение 2 запросов.
2. Это не должно быть так медленно, попробуйте EXPLAIN, чтобы увидеть, правильно ли используются индексы.
3. ИЗМЕНИТЬ ТАБЛИЦУ продуктов, ДОБАВИТЬ ИНДЕКС (каталог, стиль, скидку);
4. это ужасно. менее чем за 1 секунду на моей тестовой машине. Я думаю, мне следует заняться оптимизацией моих таблиц. еще раз спасибо! отличный ответ.
5. Исправленный ответ, в первом подзапросе был select * , но все, что нужно для ссылки на 2-й подзапрос, это просто style, max (скидка)
Ответ №2:
Взгляните на предложение «HAVING». Это должно приблизить вас. http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html
Ответ №3:
Когда вы говорите «приоритет товара со скидкой», приоритет подразумевает упорядочение, а не группировку. Вам нужно упорядочить свои результаты по discount
(я предполагаю, что это столбец, а не таблица).
Комментарии:
1. Я хочу, чтобы результаты выдавали мне поле со скидкой > 0. Если товаров со скидкой не существует, я все равно хочу получить результаты. видите ли, я не уверен, КАК инструкции «GROUP BY» выбирают, какую именно информацию о продукте (из всех продуктов, имеющих заданный стиль) отображать.
Ответ №4:
Я думаю, это можно сделать с помощью HAVING
предложения; предполагая, что таблица скидок является логической, 1 для скидки, 0 для отсутствия скидки:
SELECT *
FROM
products
WHERE
catalog = 1
GROUP BY
style
HAVING
discount = MAX(discount)
ORDER BY
name ASC limit 0, 100
редактировать: возможно, я неправильно истолковал вопрос. Если все, что вы хотите, это чтобы товары со скидкой появлялись первыми в вашем списке, вам нужно будет только изменить ORDER BY
предложение:
SELECT *
FROM
products
WHERE
catalog = 1
GROUP BY
style
ORDER BY
discount DESC,
name ASC
LIMIT
0, 100
Комментарии:
1. спасибо, но ни один из этих запросов не дает желаемого результата. решение piotrm, приведенное выше, выполняет эту работу.