Получить минимальное значение цены у выбираемых товаров
имеется 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