Как использовать таблицу свойств / значений в MySQL

0

Я унаследовал базу данных mysql, которая имеет таблицу с такими столбцами:

object_id, свойство, значение

Он содержит следующие данные:

1,first_name,Jane
1,last_name,Doe
1,age,10
1,color,red
2,first_name,Mike
2,last_name,Smith
2,age,20
2,color,blue
3,first_name,John
3,last_name,Doe
3,age,20
3,color,red
...

В принципе, я хочу, чтобы эта таблица рассматривалась как обычная таблица. Как мне получить идентификационные номера (или все свойства) человека, которому 20 лет, отсортировано последним и первым именем? До сих пор я:

SELECT object_id FROM table WHERE property = 'age' AND value = '20'
union
SELECT object_id FROM table WHERE property = 'color' AND value = 'red'

Но я не уверен, как упорядочить данные.

Спасибо

  • 0
    Вы хотите, чтобы все свойства для определенного идентификатора в разных столбцах (в этом случае: число свойств конечное и каковы они), или только в строке?
Теги:

3 ответа

1
Лучший ответ

Трудности воссоздания строк в модели EAV - это именно то, что вы видите.

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

Как правило, ось может быть выполнена с помощью

SELECT object_id
    ,MAX(CASE WHEN property = 'age' THEN value ELSE NULL END) AS age
    ,MAX(CASE WHEN property = 'color' THEN value ELSE NULL END) AS color
-- ...
FROM EAVTABLE
GROUP BY object_id

Тогда:

SELECT *
FROM (
    SELECT object_id
        ,MAX(CASE WHEN property = 'age' THEN value ELSE NULL END) AS age
        ,MAX(CASE WHEN property = 'color' THEN value ELSE NULL END) AS color
    -- ...
    FROM EAVTABLE
    GROUP BY object_id
) AS objects
WHERE age = '20' -- Note you may want to cast from char to proper types above (and these casts can fail).
ORDER BY last_name, first_name
  • 0
    спасибо большое, это именно то, что я искал ...
0

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

Тем не менее, если вы абсолютно застряли с тем, что у вас есть, вы можете подделать сводную таблицу на лету примерно так:

SELECT object_id, IF(property='first_name',value,NULL) AS first_name, IF(property='last_name',value,NULL) AS last_name, IF(property='age',value,NULL) AS age FROM table GROUP BY object_id;

а затем используйте это в подвыборке. Но, как сказал Донни, это будет ужасно медленным. Я предполагаю, что вы можете уничтожить набор object_id с помощью суб-select IN, но на самом деле вы не получите ничего, что отдаленно напоминало бы достойную производительность для запроса, который вы хотите получить из таблицы, подобной этой.

(Еще одна часть ужаса - числовые значения, такие как "возраст", хранятся как varchars?!?)

  • 0
    Спасибо за ответ ... Я не могу больше согласиться с тем, насколько плоха эта таблица, но я как бы застрял с ней ... Там не так много данных, поэтому не должно быть слишком плохо.
0

Таблицы свойств/значений - это действительно плохая идея, поскольку вы обнаруживаете. Они ломают то, как SQL ожидает, что данные будут представлены, они не могут быть правильно проиндексированы, yadda yadda и т.д. Это небрежное исправление для тех, кто не хочет пытаться поддерживать базу данных (или кто-то, кто благими намерениями хочет дать пользователям "расширяемость", но не рассматривает все проблемы).

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

Что касается вашего конкретного вопроса, я не уверен, поддерживает ли mysql pivot или нет. Если это произойдет, это "повернет" ваш результирующий набор в горизонтальную таблицу, которую вы можете затем заказать, как вы ожидаете. Если это не так, вы можете взломать поддельный свод с множеством операторов case и некоторую агрегацию, чтобы свернуть все строки вместе... но она неаккуратная и медленная.

  • 0
    К сожалению, в MySQL нет центра.
  • 0
    Я согласен, что это ужасная модель базы данных, но это то, с чем мне приходится работать. Спасибо за вклад ...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню