Я хотел бы получить запрос для получения размера и цвета, назначенных комбинациям. До сих пор со следующим запросом MySQL мне удавалось извлекать данные в отдельных строках, но я не мог объединять их в одну строку.
SELECT pa.`id_product_attribute`, al.`name`
FROM `psfr_product_attribute` pa
JOIN `psfr_product_attribute_combination` pac ON(pa.`id_product_attribute` = pac.`id_product_attribute`)
JOIN `psfr_attribute_lang` al ON(pac.`id_attribute` = al.`id_attribute`)
WHERE `id_product` = 59 AND al.`id_lang` = 1 AND pa.`quantity` > 0
ORDER BY pa.`id_product_attribute`
Результат:
195 M
195 RED
197 L
197 RED
199 XL
199 RED
200 XL
200 BLACK
201 S
201 RED
202 S
202 BLACK
Как я могу изменить запрос, чтобы получить такой результат?
195 M RED
197 L RED
199 XL RED
200 XL BLACK
201 S RED
202 S BLACK
Любая помощь будет принята с благодарностью.
Таблицы:
CREATE TABLE `psfr_product_attribute` (
`id_product_attribute` int UNSIGNED NOT NULL,
`id_product` int UNSIGNED NOT NULL,
`quantity` int NOT NULL DEFAULT '0',
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
INSERT INTO `psfr_product_attribute` (`id_product_attribute`, `id_product`, `quantity`) VALUES
(195, 59, 5),
(196, 59, 0),
(197, 59, 5),
(198, 59, 0),
(199, 59, 5),
(200, 59, 5),
(201, 59, 5),
(202, 59, 5);
CREATE TABLE `psfr_product_attribute_combination` (
`id_attribute` int UNSIGNED NOT NULL,
`id_product_attribute` int UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
INSERT INTO `psfr_product_attribute_combination` (`id_attribute`, `id_product_attribute`) VALUES
(2, 195),
(10, 195),
(2, 196),
(11, 196),
(3, 197),
(10, 197),
(3, 198),
(11, 198),
(4, 199),
(10, 199),
(4, 200),
(11, 200),
(1, 201),
(10, 201),
(1, 202),
(11, 202);
CREATE TABLE `psfr_attribute_lang` (
`id_attribute` int NOT NULL,
`id_lang` int NOT NULL,
`name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `psfr_attribute_lang` (`id_attribute`, `id_lang`, `name`) VALUES
(1, 1, 'S'),
(1, 8, 'S'),
(2, 1, 'M'),
(2, 8, 'M'),
(3, 1, 'L'),
(3, 8, 'L'),
(4, 1, 'XL'),
(4, 8, 'XL'),
(10, 1, 'Red'),
(10, 8, 'Vermelho'), //Red
(11, 1, 'Black'),
(11, 8, 'Preto'); //Black
Я не использовал следующие таблицы в своем запросе, но также оставил их, потому что не знаю, могут ли они быть полезны:
CREATE TABLE `psfr_attribute` (
`id_attribute` int NOT NULL,
`id_attribute_group` int NOT NULL,
`color` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`position` int NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `psfr_attribute` (`id_attribute`, `id_attribute_group`, `color`, `position`) VALUES
(1, 1, '', 0),
(2, 1, '', 1),
(3, 1, '', 2),
(4, 1, '', 3),
(10, 2, '#E84C3D', 5),
(11, 2, '#434A54', 6);
CREATE TABLE `psfr_attribute_group` (
`id_attribute_group` int NOT NULL,
`is_color_group` tinyint(1) NOT NULL,
`group_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`position` int NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `psfr_attribute_group` (`id_attribute_group`, `is_color_group`, `group_type`, `position`) VALUES
(1, 0, 'radio', 1),
(2, 1, 'color', 0),
(4, 0, 'select', 2);
В мой ответ добавлен пример того, как это сделать после того, как вы получили длинный список.
@RinkeshP Спасибо, но мне нужно, чтобы Размер и Цвет были в отдельных столбцах.
Обратите внимание: нет необходимости изменять исходный запрос, так как вы можете просто разделить их и объединить постфактум.
@н.х. не могли бы вы упомянуть свои структуры таблиц? цвета и размеры фиксированы? И все ли размеры и цвета входят в столбец атрибутов?
Предоставьте образец исходных данных как CREATE TABLE (пропустите лишние столбцы) + INSERT INTO (7-10 строк) и желаемый результат для этих данных. Подсказка: соедините 2 копии таблицы атрибутов.
@Akina Только что обновил свой вопрос со структурой таблицы. Спасибо.
@RinkeshP Только что обновил свой вопрос со структурой таблицы. Спасибо.
Есть несколько способов сделать это, но, в конце концов, трудно предложить лучшее решение, не видя исходных таблиц. Таким образом, мы не можем видеть, есть ли какие-либо идентификаторы, разделяющие типы атрибутов, или какие-либо другие категории.
Но, проще говоря. Предполагая, что у вас только до XL, а не до XXL - тогда можно просто посчитать количество символов так, что если 2 или меньше, то это размер, если 3 и больше, то это цвет.
Затем вы можете объединить эти две категории вместе. Если это невозможно из-за того, что размеры выше XL, просто укажите и «Где al.´name´ в ('XS', 'S', 'M', 'L', 'XL', 'XXL') - пометьте это как размер, затем сделайте полную противоположность (где нет) и соедините оба этих столбца в первой строке, которую вы показываете, идентификатор.
Вот пример:
CREATE TABLE #list (
Id int,
Attribute varchar(255),
)
insert into #list (Id, Attribute)
Values (195, 'M'),
(195, 'RED'),
(197, 'L'),
(197, 'RED'),
(199, 'XL'),
(199, 'RED'),
(200, 'XL'),
(200, 'BLACK'),
(201, 'S'),
(201, 'RED'),
(202, 'S'),
(202, 'BLACK');
--Start from here, everything above is to fit your example data
select *
into #first
from #list a
where a.Attribute in ('XS', 'S', 'M', 'L', 'XL', 'XXL')
select a.Id, a.Attribute as 'Color', b.Attribute as 'Size'
from #list a
join #first b
on a.Id=b.Id and b.Attribute!=a.Attribute
drop table #list
drop table #first
SELECT pa.id_product_attribute,
al1.name size,
al2.name color
FROM psfr_product_attribute pa
JOIN psfr_product_attribute_combination pac1 ON pa.id_product_attribute = pac1.id_product_attribute
JOIN psfr_attribute_lang al1 ON pac1.id_attribute = al1.id_attribute
JOIN psfr_product_attribute_combination pac2 ON pa.id_product_attribute = pac2.id_product_attribute
JOIN psfr_attribute_lang al2 ON pac2.id_attribute = al2.id_attribute
WHERE pa.id_product = 59
AND al1.id_attribute IN (1,2,3,4)
AND al2.id_attribute IN (10,11)
AND al1.id_lang = 1
AND al2.id_lang = 1
AND pa.quantity > 0
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=2bdb34596360be343171bf90d8ca4849
Спасибо. Как я могу изменить запрос таким образом, чтобы IN (1,2,3,4)
и IN (10,11)
могли заполняться динамически? Потому что таблица psfr_attribute
со временем будет увеличиваться.
@н.х. Создайте столбец категорий атрибутов в psfr_attribute_lang
(1 - размер, 2 - цвет и т. д., возможно, как ссылку на таблицу категорий) и используйте его в ГДЕ вместо отдельного списка атрибутов.
Это не связано, но, возможно, вы хотите немного изменить структуру своей таблицы, сохраняя отдельные поиски по размеру, цвету и другим атрибутам. Но пока динамическая сводка может решить вашу проблему. В основном это условное преобразование ваших строк в столбцы, избегая дополнительных объединений. Это можно легко расширить, чтобы разделить другие классы атрибутов на большее количество столбцов, просто добавив необходимый оператор MAX (CASE
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=45c1fd5bac7382b0aa121c107267e9e1
Спасибо. К сожалению, я не могу изменить структуру таблицы.
Не могли бы вы дать мне несколько советов о том, как я могу получить, если это возможно, IN()
, заполненный на основе таблиц psfr_attribute
и psfr_attribute_group
? Благодарю вас!
это действительно зависит от контекста, на данный момент то, что разделяет цвета и размеры в этом столбце, заключается в том, что мы знаем, что такое цвета и размеры. Можно утверждать, что даже BIG — это размер, который может быть сохранен как B в размерах, тогда вам также потребуется динамически обрабатывать B, чтобы быть включенным в размеры. Если у вас нет сопоставления (например, дополнительного столбца attribute_type) для различения значений, я не вижу способа, которым вы можете их различать. Вы можете добавлять к атрибутам префикс «size_» или «color_» и использовать регулярные выражения, чтобы избежать дополнительного столбца, но это будет очень неэффективно при увеличении объема данных.
Зная, что sizes
принадлежит id_attribute_group=1
, сделал подзапрос внутри IN()
, и он работает. Думаю, это неэффективный способ сделать это, так как я дублирую запросы. Есть ли другой способ? dbfiddle.uk/…
он не будет хорошо масштабироваться, дополнительные соединения будут снижать производительность, и я не видел никаких индексов в таблицах, поэтому, вероятно, он выполняет полное сканирование таблицы, что плохо. Но для текущего экземпляра схемы и с точки зрения логики это будет работать.
посмотри как пользоваться
group_concat()