Расширенная фильтрация в интернет-магазине с MySQL - PullRequest
0 голосов
/ 26 декабря 2018

Я делаю интернет-магазин на MySQL и PHP с дизайном базы данных , похожим на этот (см. Рисунок)
У меня нет проблем с предметами с несколькими ценами с разными спецификациями, как ввопрос, связанный выше.

Это будет компьютерный интернет-магазин, поэтому мне не нужно составлять спецификации для каждого продукта.Я могу классифицировать их, например.Смартфоны, Ноутбуки ... и добавьте спецификации для каждой категории.
Смартфоны могут иметь: Бренд, Тип процессора, Размер экрана, Цвет, Батарея, Цена и т. Д.
Ноутбуки: Процессор, Видеокарта, Бренд, Цена,Размер, ...

Я также не вижу необходимости в таблице [combinations], так как, по моему мнению, много было бы ненужного для хранения.

Моя проблема с фильтрацией продуктов.Я могу легко выбрать все из них, или только один, или, например.выберите все телефоны белого цвета или все телефоны белого или золотого цвета, но я не могу выбрать все телефоны белого цвета с 8-мегапиксельной фронтальной камерой.

Структура таблицы:
[products]: идентификатор, имя, идентификатор категории, описание

[categories]: идентификатор, имя

[specifications]: идентификатор, идентификатор категории, имя

[spec_values]:id, product_id, spec_id, value

Следующий SQL возвращает все отдельные продукты, которые имеют золотой цвет или имеют 8-мегапиксельную фронтальную камеру.

SELECT products.id, products.name, spec_values.value AS Filter
FROM products, categories, specifications, `spec_values` 
WHERE products.category_id = categories.id 
    AND spec_values.product_id = products.id 
    AND ((specifications.name = 'Color' AND spec_values.value = 'Gold') 
        OR (specifications.name = 'Front Camera' AND spec_values.value = '8MP')) 
GROUP BY products.id;

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

Одним из решений будет SQL CREATE TEMPORARY TABLEдля каждого фильтра, но я думаю, что это потребовало бы большого количества ненужной работы на стороне сервера.

Другой вариант - получить все непонятные значения и перебрать их с помощью PHP и проверить, все лиони существуют;если да, то отобразите их на странице, но, тем не менее, это тоже может быть грязно.

Есть ли лучшее решение, которое я не заметил из-за моей неопытности в SQL?Спасибо заранее за любую помощь.Хорошего дня!

1 Ответ

0 голосов
/ 26 декабря 2018

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

SELECT products.id,
       products.name
       FROM products
            INNER JOIN spec_values
                       ON spec_values.product_id = products.id 
            INNER JOIN specifications
                       ON specifications.id = spec_values.spec_id
       WHERE specifications.name = 'Color' AND spec_values.value = 'Gold'
              OR specifications.name = 'Front Camera' AND spec_values.value = '8MP'
       GROUP BY products.id,
                products.name
       HAVING count(*) = 2;

Кстати, рекомендуется использовать явный синтаксис соединения над списком с разделителями-запятыми впредложение FROM для лучшей читаемости.

...