Создайте матрицу / таблицу из ЛЕВОГО СОЕДИНЕНИЯ в SQL

StackOverflow https://stackoverflow.com/questions/1153325

  •  18-09-2019
  •  | 
  •  

Вопрос

Я хотел бы знать хорошее решение для преобразования ЛЕВОГО СОЕДИНЕНИЯ в таблицу / матрицу.

Например, учитывая эту схему:

objects
   id (integer)
   name (string)

attributes
   id (integer)
   object_id (integer)
   name (string)
   value (string)

И эти ценности:

1,ball
2,box

1,1,colour,red
2,1,shape,sphere
3,1,material,rubber
4,2,colour,brown
5,2,shape,cube

Я бы хотел получить это:

object_id | object_name | colour | shape  | material

1         | ball        | red    | sphere | rubber
2         | box         | brown  | cube   | NULL

В идеале это было бы с неизвестным количеством атрибутов для каждого объекта и для MySQL без использования хранимых процедур.

Это было полезно?

Решение

То, что с СУБДs заключается в том, что их цель - хранить и представлять то, что у вас уже есть.Создание столбцов динамически никогда не предполагалось.

Это случай, который должен быть обработан на клиенте, который должен представить данные.

Не обращая внимания на то, как предполагается использовать РСУБД, вы все равно не найдете простого способа сделать это.Особенно, если вы не хотите, чтобы список столбцов был динамическим.Вы можете создать динамический SQL-запрос и выполнить его, но нет способа написать стандартный SQL-запрос и получить этот результат (поскольку вы всегда указываете все столбцы явно, используя *, но в данном случае это не может быть использовано в ваших интересах.)

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

Вы не можете сделать это без использования динамических запросов в SQL.

Любой набор SQL сделки с предполагают фиксированное количество столбцов с фиксированными именами.

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

Например, представьте представление, созданное по запрашиваемому вами запросу (если бы это было возможно).:

SELECT  object_id, colour
FROM    myquery

Компилируется это представление или нет, будет зависеть от результатов запроса, и это приведет к ошибкам во время выполнения (с которыми трудно справиться) вместо простого пустого результирующего набора (с которым легко справиться).

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

Если у вас есть attribute_names таблицу, которая содержит все возможные названия ваших атрибутов, вы можете сделать примерно так:

SELECT  o.name, an.name, a.value
FROM    objects o
CROSS JOIN
        attribute_names an
LEFT JOIN
        attributes a
ON      a.object = o.id
        AND a.name = an.name

, который будет содержать все возможные object_id / attribute_name связывается с соответствующими значениями, и вы можете использовать его на стороне клиента для более легкого заполнения матрицы.

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

insert into merged (object_id, object_name) select id, name from objects;
update merged m inner join attributes a on a.object_id = m.object_id and a.name = 'colour' set m.colour = a.value;
update merged m inner join attributes a on a.object_id = m.object_id and a.name = 'material' set m.material = a.value;
update merged m inner join attributes a on a.object_id = m.object_id and a.name = 'shape' set m.shape = a.value;

Хм, возможно, вам просто не хватает 2 логических шагов, чтобы это произошло.

Что вам нужно, так это таблица attributeTypes и таблица AttributeValues.

objects
   id (integer)
   name (string)

attribute_types
   id (integer)
   name (string)
   description (string)
   enabled (bit)

attribute_values
   id (integer)
   attribute_type_id (integer)
   value (string)
   enabled (bit)

attributes
   id (integer)
   object_id (integer)
   attribute_type_id (integer)
   attribute_value_id (integer)

Таким образом, объект может иметь атрибуты, эти атрибуты задаются идентификаторами attribute_type_id и attribute_value_id.

Затем это позволяет вам иметь объект с несколькими атрибутами..

например

object 
-> 1, ball

attribute_types
-> 10, Colour, null, enabled
-> 20, Shape, null, enabled
-> 30, Material, null, enabled

attribute_values 
-> 100, 10, blue, enabled
-> 200, 10, red, enabled
-> 300, 10, green, enabled

-> 400, 20, round, enabled
-> 500, 20, square, enabled
-> 600, 20, triangle, enabled

Таким образом, атрибут будет выглядеть следующим образом:

attributes
-> 1000, 1, 10, 100 // this item has a color and it is blue
-> 1001, 1, 20, 400 // this item has a shape and it is round
-> 1002, 1, 10, 200 // this item has a color and it is red

Таким образом, теперь объекты могут иметь несколько атрибутов, которые определяют их значения в разных таблицах.Теперь важный вопрос, как вы это запрашиваете?Возможно, вам придется разделить запрос на несколько частей, в зависимости от того, насколько силен ваш sql.

@attribute_type_id = select Id from attribute_types where name = 'Color' // 10

select * from objects 
inner join attributes on objects.id = attributes.object_id
inner join attribute_values on objects.attribute_value_id = attribute_values.id
where attribute_type_id = @attribute_type_id
and attribute_values.value= 'blue'

И вот оно, вы должны вернуть каждый объект, у которого есть attribute_type цвета и attribute_value синего.

Мой Sql не настолько силен, но вы должны быть в состоянии выполнять более одного предложения, если хотите выполнять поиск по нескольким атрибутам одновременно.На мой взгляд, attribute_type_id в таблице attributes не присоединяется к таблице attribute_type, но это может быть сделано для облегчения выполнения запроса за 1 заход, хотя с точки зрения производительности у меня это есть, так что это ускорит запросы за счет отсутствия необходимости присоединяться к таблице, но разница может быть незначительной в зависимости от того, насколько большим все становится.

Примечание:Обычно я работаю с msssql, а не mysql, поэтому, если типы баз данных не совпадают, вот почему.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top