Получить минимальное значение цены у выбираемых товаров

имеется 4 таблицы

Таблица, где хранится основная инфа о товарах.

 CREATE TABLE `oc_product` (
 `product_id` int NOT NULL AUTO_INCREMENT,
 `model` varchar(64) NOT NULL,
 `quantity` int NOT NULL DEFAULT '0',
 `image` varchar(255) DEFAULT NULL,
 `manufacturer_id` int NOT NULL,
 `price` decimal(15,4) NOT NULL DEFAULT '0.0000',
 `date_available` date NOT NULL DEFAULT '1990-09-02',
 `inlay` varchar(255) DEFAULT NULL,
 `sort_order` int NOT NULL DEFAULT '0',
 `status` tinyint(1) NOT NULL DEFAULT '0',
 PRIMARY KEY (`product_id`),
 KEY `quantity` (`quantity`),
 KEY `status` (`status`),
 KEY `image` (`image`),
 KEY `manufacturer_id` (`manufacturer_id`),
 KEY `price` (`price`),
 KEY `model` (`model`)
) ENGINE=InnoDB AUTO_INCREMENT=41298 DEFAULT CHARSET=utf8

Таблица, хранящая акционные цены

CREATE TABLE `oc_product_discount` (
 `product_discount_id` int NOT NULL AUTO_INCREMENT,
 `product_id` int NOT NULL,
 `customer_group_id` int NOT NULL,
 `quantity` int NOT NULL DEFAULT '0',
 `priority` int NOT NULL DEFAULT '1',
 `price` decimal(15,4) NOT NULL DEFAULT '0.0000',
 `date_start` date NOT NULL DEFAULT '1990-10-10',
 `date_end` date NOT NULL DEFAULT '2025-10-10',
 PRIMARY KEY (`product_discount_id`),
 KEY `product_id` (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Таблица, хранящая информацию о скидках

CREATE TABLE `oc_product_special` (
 `product_special_id` int NOT NULL AUTO_INCREMENT,
 `product_id` int NOT NULL,
 `customer_group_id` int NOT NULL,
 `priority` int NOT NULL DEFAULT '1',
 `price` decimal(15,4) NOT NULL DEFAULT '0.0000',
 `date_start` date NOT NULL DEFAULT '1990-10-10',
 `date_end` date NOT NULL DEFAULT '2025-10-10',
 PRIMARY KEY (`product_special_id`),
 KEY `product_id` (`product_id`),
 KEY `special_price` (`price`)
) ENGINE=InnoDB AUTO_INCREMENT=15752 DEFAULT CHARSET=utf8

Таблица с атрибутами

CREATE TABLE `oc_product_attribute` (
 `product_id` int NOT NULL,
 `attribute_id` int NOT NULL,
 `language_id` int NOT NULL,
 `text` text NOT NULL,
 PRIMARY KEY (`product_id`,`attribute_id`,`language_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Есть основной запрос, получающий список товаров, которые группируем по артикулу, но получается так, что Mysql во время Group by отдает product_id с не самой низкой ценой, а задача в том, чтобы получать именно с самой низкой. Средняя скорость выполнения запроса 0.0081 c

SELECT
    p.model,
    p.product_id,
    p.price
    ,  
    (
    SELECT
        price
    FROM
        oc_product_discount pd2
    WHERE
        pd2.product_id = p.product_id AND pd2.quantity > 0 AND(
            (
                pd2.date_start = '1990-10-10' OR pd2.date_start < '2021-01-20 06:18:00'
            ) AND(
                pd2.date_end = '1990-10-10' OR pd2.date_end > '2021-01-20 06:18:00'
            )
        )
    ORDER BY
        pd2.priority ASC,
        pd2.price ASC
    LIMIT 1
) AS discount,(
SELECT
    price
FROM
    oc_product_special ps
WHERE
    ps.product_id = p.product_id AND(
        (
            ps.date_start = '1990-10-10' OR ps.date_start < '2021-01-20 06:18:00'
        ) AND(
            ps.date_end = '1990-10-10' OR ps.date_end > '2021-01-20 06:18:00'
        )
    )
ORDER BY
    ps.priority ASC,
    ps.price ASC
LIMIT 1
) AS special
FROM
    oc_product AS p
INNER JOIN
    oc_product_to_category p2c
ON
    (p.product_id = p2c.product_id)
WHERE
    p.quantity > 0 AND p.status > 0 AND p.image IS NOT NULL AND p.price BETWEEN -1 AND 1000000 AND p2c.category_id IN (24, 31)
LIMIT 0, 60

План запроса

Первым, что пришло в голову обернуть основной запрос в ещё один, сортируя во вложенном по возрастанию, сделать получилось, но скорость выполнения увеличилась до 0.2342 сек

SELECT price, product_id, model FROM
(SELECT
    p.model,
    p.product_id,
    p.price,  
    (
    SELECT
        price
    FROM
        oc_product_discount pd2
    WHERE
        pd2.product_id = p.product_id AND pd2.quantity > 0 AND(
            (
                pd2.date_start = '1990-10-10' OR pd2.date_start < '2021-01-20 06:18:00'
            ) AND(
                pd2.date_end = '1990-10-10' OR pd2.date_end > '2021-01-20 06:18:00'
            )
        )
    ORDER BY
        pd2.priority ASC,
        pd2.price ASC
    LIMIT 1
) AS discount,(
SELECT
    price
FROM
    oc_product_special ps
WHERE
    ps.product_id = p.product_id AND(
        (
            ps.date_start = '1990-10-10' OR ps.date_start < '2021-01-20 06:18:00'
        ) AND(
            ps.date_end = '1990-10-10' OR ps.date_end > '2021-01-20 06:18:00'
        )
    )
ORDER BY
    ps.priority ASC,
    ps.price ASC
LIMIT 1
) AS special
FROM
    oc_product p
INNER JOIN
    oc_product_attribute AS pa1
ON
    (p.product_id = pa1.product_id)
WHERE
    p.quantity > 0 AND p.status > 0 AND p.image IS NOT NULL AND pa1.attribute_id IN(7, 12, 154) AND p.price BETWEEN -1 AND 1000000 ORDER BY p.price ASC) AS tab
GROUP BY model
LIMIT 0, 60

И перестал работать индекс

План запроса

Пробовали в первоначальной версии запроса отменять сортировку у GROUP BY при помощи ORDER BY NULL, но не помогает.

Пробовали FORCE-ить индекс тоже не помогает.

Может есть какой-то более "легкий" вариант для решения нашей задачи?

Версия Mysql 8.0.22


Ответы (0 шт):