динамическая сводная таблица sql - PullRequest
1 голос
/ 18 декабря 2009

Я надеюсь, что вы можете помочь мне с решением этой задачи, которую мы имеем.

изначально у нас есть эти таблицы:

hwtype
id  name
1   router
2   switch

hwelement
id   idhwtype  name
1    1         RTR1
2    1         RTR2
3    2         SWT1

hwattributes
id  idhwtype name
1   1        speed
2   1        IP
3   2        ports

hwtypeattributes
id  idhwelement    idhwattribute value
1   1              1             100mb
2   1              2             172.16.3.23
3   2              1             10mb
4   2              2             172.16.3.26
5   3              3             8

сейчас нам нужна функция, которая представляет данные таким образом (в соответствии с типом hw)

для hwtype.name = router

element   speed  IP
RTR1      100mb  172.16.3.23
RTR2      10mb   172.16.3.26

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

Я искал примеры, но, к сожалению, я нашел хорошие, которые выполняют агрегирование по значениям, что я не учел.

Заранее спасибо за помощь

1 Ответ

0 голосов
/ 18 декабря 2009

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

Прочтите статью " Bad CaRMa ", чтобы узнать, как система EAV разрушила компанию.

Вот что вам нужно сделать, чтобы получить атрибуты маршрутизатора из вашей базы данных:

SELECT e.name AS "element", 
       speedval.value AS "speed", 
       ipval.value AS "IP",
       portsval.value AS "Ports"
FROM hwtype t 
JOIN hwelement e ON (e.idhwtype = t.id)
JOIN hwattributes speed ON (speed.idhwtype = t.id AND speed.name = 'speed')
LEFT OUTER JOIN hwtypeattributes speedval 
  ON (speedval.idhwattribute = speed.id AND speedval.idhwelement = e.id)
JOIN hwattributes ip ON (ip.idhwtype = t.id AND ip.name = 'ip')
LEFT OUTER JOIN hwtypeattributes ipval 
  ON (ipval.idhwattribute = ip.id AND ipval.idhwelement = e.id)
JOIN hwattributes ports ON (ports.idhwtype = t.id AND ports.name = 'ports')
LEFT OUTER JOIN hwtypeattributes portsval 
  ON (portsval.idhwattribute = ports.id AND portsval.idhwelement = e.id)
WHERE t.name = 'router';

Обратите внимание, что вам нужна дополнительная пара соединений для каждого атрибута , если вы настаиваете на получении всех атрибутов для данного элемента в одной строке. Это быстро становится чрезмерно дорогим для оптимизатора SQL.

Гораздо проще извлечь атрибуты из нескольких строк и отсортировать их в коде приложения:

SELECT e.name AS "element", a.name, v.value
FROM hwtype t 
JOIN hwelement e ON (e.idhwtype = t.id)
JOIN hwattributes a ON (a.idhwtype = t.id)
JOIN hwtypeattributes v ON (v.idhwattribute = a.id AND v.idhwelement = e.id)
WHERE t.name = 'router';
...