Opencart. Функция getProductSpecials, модифировать запрос для вывода дополнительных товаров
Всем привет. Помогите разобраться.
Дано:
Имеется функция getProductSpecials в catalog/model/catalog/product.php Используется для вывода товаров на странице с акциями.
Задача:
Необходимо дополнительно вывести на странице с акциями, товары, у которых поле fake_special > 0 в oc_product
Код оригинал
$sql = "SELECT DISTINCT ps.product_id, (
SELECT AVG(rating) FROM " . DB_PREFIX . "review r1
WHERE r1.product_id = ps.product_id AND r1.status = '1'
GROUP BY r1.product_id) AS rating
FROM " . DB_PREFIX . "product_special ps
LEFT JOIN " . DB_PREFIX . "product p ON (ps.product_id = p.product_id)
LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id)
LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id)
WHERE p.status = '1'
AND p.date_available <= NOW()
AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'
AND ps.customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "'
AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW())
AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW()))
GROUP BY ps.product_id";
Получилось частично решить вопрос, объединив два SELECT с помощью UNION, дополнительные товары вывелись.
$sql = "SELECT ps.product_id, (
SELECT AVG(rating) FROM " . DB_PREFIX . "review r1
WHERE r1.product_id = ps.product_id AND r1.status = '1'
GROUP BY r1.product_id) AS rating
FROM " . DB_PREFIX . "product_special ps
LEFT JOIN " . DB_PREFIX . "product p ON (ps.product_id = p.product_id)
LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id)
LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id)
WHERE p.status = '1'
AND p.date_available <= NOW()
AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'
AND ps.customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "'
AND ((ps.date_start = '0000-00-00' OR ps.date_start < NOW())
AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW()))
GROUP BY ps.product_id
UNION
SELECT p.product_id, (
SELECT AVG(rating) FROM " . DB_PREFIX . "review r1
WHERE r1.product_id = p.product_id AND r1.status = '1'
GROUP BY r1.product_id) AS rating
FROM " . DB_PREFIX . "product p
LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id)
LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id)
WHERE p.status = '1'
AND p.fake_special > '0'
AND p.date_available <= NOW()
AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'
GROUP BY p.product_id";
Но вылезла проблема с сортировкой, при ORDER BY p.sort_order например, вылезает ошибка Fatal error: Uncaught Exception: Error: Table 'p' from one of the SELECTs cannot be used in field list
Не получается объединить оба SELECT под одним ORDER BY.
UPDATE Готовое решение
$sql = "SELECT p.product_id, (
SELECT AVG(rating) FROM " . DB_PREFIX . "review r1
WHERE r1.product_id = ps.product_id AND r1.status = '1'
GROUP BY r1.product_id) AS rating
FROM " . DB_PREFIX . "product p
LEFT JOIN " . DB_PREFIX . "product_special ps ON (ps.product_id = p.product_id)
LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id)
LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id)
WHERE p.status = '1'
AND p.date_available <= NOW()
AND (ps.customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "' OR p.fake_special > '0')
AND (((ps.date_start = '0000-00-00' OR ps.date_start < NOW())
AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW())) OR p.fake_special > '0')
GROUP BY p.product_id";
Ответы (1 шт):
ORDER BY, в вашем случае, сортирует результирующую выборку двух SELECT, в которой нет p.sort_order. Такая запись сработает (у меня норм, mariadb):
SELECT p.product_id, p.sort_order as any_alias,
...
UNION
...
SELECT p.product_id, p.sort_order as any_alias,
...
ORDER BY any_alias
В любом случае UNION для этой задачи не нужен. Этот же набор данных можно достать через таблицу product (будет даже немного быстрее):
SELECT p.product_id, (
SELECT AVG(rating) FROM " . DB_PREFIX . "review r1
WHERE r1.product_id = ps.product_id AND r1.status = '1'
GROUP BY r1.product_id) AS rating
FROM " . DB_PREFIX . "product p
LEFT JOIN " . DB_PREFIX . "product_special ps ON (ps.product_id = p.product_id)
LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id)
LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id)
WHERE p.status = '1'
AND p.date_available <= NOW()
AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'
AND ps.customer_group_id = '" . (int)$this->config->get('config_customer_group_id') . "'
AND (((ps.date_start = '0000-00-00' OR ps.date_start < NOW())
AND (ps.date_end = '0000-00-00' OR ps.date_end > NOW())) OR p.fake_special > '0')