Объединить строки с запросом MySQL

Я хотел бы получить запрос для получения размера и цвета, назначенных комбинациям. До сих пор со следующим запросом 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);

посмотри как пользоваться group_concat()

Rinkesh P 22.03.2022 12:30

В мой ответ добавлен пример того, как это сделать после того, как вы получили длинный список.

Stoff 22.03.2022 12:38

@RinkeshP Спасибо, но мне нужно, чтобы Размер и Цвет были в отдельных столбцах.

n.h. 22.03.2022 12:45

Обратите внимание: нет необходимости изменять исходный запрос, так как вы можете просто разделить их и объединить постфактум.

Stoff 22.03.2022 12:49

@н.х. не могли бы вы упомянуть свои структуры таблиц? цвета и размеры фиксированы? И все ли размеры и цвета входят в столбец атрибутов?

Rinkesh P 22.03.2022 12:53

Предоставьте образец исходных данных как CREATE TABLE (пропустите лишние столбцы) + INSERT INTO (7-10 строк) и желаемый результат для этих данных. Подсказка: соедините 2 копии таблицы атрибутов.

Akina 22.03.2022 12:58

@Akina Только что обновил свой вопрос со структурой таблицы. Спасибо.

n.h. 22.03.2022 14:10

@RinkeshP Только что обновил свой вопрос со структурой таблицы. Спасибо.

n.h. 22.03.2022 14:10
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
8
77
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Но, проще говоря. Предполагая, что у вас только до 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 со временем будет увеличиваться.

n.h. 22.03.2022 14:48

@н.х. Создайте столбец категорий атрибутов в psfr_attribute_lang (1 - размер, 2 - цвет и т. д., возможно, как ссылку на таблицу категорий) и используйте его в ГДЕ вместо отдельного списка атрибутов.

Akina 22.03.2022 14:50
Ответ принят как подходящий

Это не связано, но, возможно, вы хотите немного изменить структуру своей таблицы, сохраняя отдельные поиски по размеру, цвету и другим атрибутам. Но пока динамическая сводка может решить вашу проблему. В основном это условное преобразование ваших строк в столбцы, избегая дополнительных объединений. Это можно легко расширить, чтобы разделить другие классы атрибутов на большее количество столбцов, просто добавив необходимый оператор MAX (CASE

https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=45c1fd5bac7382b0aa121c107267e9e1

Спасибо. К сожалению, я не могу изменить структуру таблицы.

n.h. 22.03.2022 15:41

Не могли бы вы дать мне несколько советов о том, как я могу получить, если это возможно, IN(), заполненный на основе таблиц psfr_attribute и psfr_attribute_group? Благодарю вас!

n.h. 22.03.2022 15:59

это действительно зависит от контекста, на данный момент то, что разделяет цвета и размеры в этом столбце, заключается в том, что мы знаем, что такое цвета и размеры. Можно утверждать, что даже BIG — это размер, который может быть сохранен как B в размерах, тогда вам также потребуется динамически обрабатывать B, чтобы быть включенным в размеры. Если у вас нет сопоставления (например, дополнительного столбца attribute_type) для различения значений, я не вижу способа, которым вы можете их различать. Вы можете добавлять к атрибутам префикс «size_» или «color_» и использовать регулярные выражения, чтобы избежать дополнительного столбца, но это будет очень неэффективно при увеличении объема данных.

Rinkesh P 22.03.2022 16:41

Зная, что sizes принадлежит id_attribute_group=1, сделал подзапрос внутри IN(), и он работает. Думаю, это неэффективный способ сделать это, так как я дублирую запросы. Есть ли другой способ? dbfiddle.uk/…

n.h. 22.03.2022 18:12

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

Rinkesh P 23.03.2022 04:13

Другие вопросы по теме