SQL Oracle - декодирование таблицы атрибут-сущность-сущность с повторением сущности - PullRequest
0 голосов
/ 04 июля 2018

У меня есть следующая таблица, основанная на системе значений атрибутов сущностей (поэтому для каждого элемента есть строка с атрибутом и его значением):

+----------+-----------+---------+
| EntityID | Attribute | Value   |
+----------+-----------+---------+
| 1        | Name      | Item 1  |
+----------+-----------+---------+
| 1        | Age       | 2       |
+----------+-----------+---------+
| 1        | Cost      | 100     |
+----------+-----------+---------+
| 1        | Cost      | 250     |
+----------+-----------+---------+
| 2        | Name      | Item 2  |
+----------+-----------+---------+
| 2        | Age       | Unknown |
+----------+-----------+---------+
| 2        | Age       | 3       |
+----------+-----------+---------+
| 2        | Cost      | 125     |
+----------+-----------+---------+

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

+----------+--------+-----+-----------+
| EntityID | Name   | Age | Cost      |
+----------+--------+-----+-----------+
| 1        | Item 1 | 2   | 100 - 250 |
+----------+--------+-----+-----------+
| 2        | Item 2 | 3   | 125       |
+----------+--------+-----+-----------+

Как видите, один и тот же атрибут может существовать или не существовать несколько раз. И в зависимости от атрибута я могу захотеть объединить (в данном случае объединить стоимость как min и max) или проигнорировать один из ответов, который не имеет смысла (в этом случае неизвестен для возраста, возможно с функцией CASE WHEN ).

В настоящее время я использую функцию DECODE, которая изменяет атрибуты на столбцы и принимает максимум:

SELECT  ENTITYID
        ,MAX(DECODE(ATTRIBUTE, 'Name', VALUE)) AS "Name"
        ,MAX(DECODE(ATTRIBUTE, 'Age', VALUE)) AS "Age"
        ,MAX(DECODE(ATTRIBUTE, 'Cost', VALUE)) AS "Cost"
FROM    DECODING
GROUP BY ENTITYID;

Очевидно, что он не работает, если нужно выбирать между значениями, так как он принимает макс. Как я могу лечить эти случаи, зная, что моя таблица содержит более 50 атрибутов? Вот результат.

+----------+--------+---------+------+
| EntityID | Name   | Age     | Cost |
+----------+--------+---------+------+
| 1        | Item 1 | 2       | 250  |
+----------+--------+---------+------+
| 2        | Item 2 | Unknown | 125  |
+----------+--------+---------+------+

Спасибо!

1 Ответ

0 голосов
/ 04 июля 2018

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

SELECT ENTITYID,
       MAX(CASE WHEN ATTRIBUTE = 'Name' THEN VALUE END) AS Name,
       MAX(CASE WHEN ATTRIBUTE = 'Age' AND VALUE <> 'UNKNOWN' THEN VALUE END) AS Age,
       (MIN(CASE WHEN ATTRIBUTE = 'Cost' THEN Value END) ||
        (CASE WHEN COUNT(DISTINCT CASE WHEN ATTRIBUTE = 'Cost' THEN Value END) > 1
              THEN '-' || MAX(CASE WHEN ATTRIBUTE = 'Cost' THEN Value END)
         END)
        ) as Cost
FROM DECODING
GROUP BY ENTITYID;

Я рекомендую использовать CASE выражения вместо DECODE(). CASE - это синтаксис стандарта ANSI и немного более гибкий.

...