Объедините несколько строк в одну после группы по - PullRequest
0 голосов
/ 19 мая 2018

ОБНОВЛЕНИЕ: https://www.db -fiddle.com / f / 5fGUTSsAhGRPYPk33wDSzz / 0

Извините за вопрос, очень похожий на предыдущий, но яя действительно застрял здесь.

Есть несколько таблиц:

  • items → items_roles → роли
  • items → зоны → role_zones → role

Структура:

  • items: id, zone_id
  • items_roles: role_id, item_id
  • zone: id
  • role_zones: role_id, zone_id
  • role: id, role_type_id,

Я пытаюсь добавить поля ролей к элементам, он должен принимать role_type, и это значение из items_zones, и если это NULL, получить запасное значение из зоны(role_zones).

Я начал с:

SELECT 
    items.id,
    (z_roles.role_type_id) as z_role_type_id,
    (z_roles.id) as z_role_id,
    MAX(i_roles.role_type_id) as i_role_type_id,
    MAX(i_roles.id) as i_role_id
FROM 
    items
LEFT JOIN 
    zones as j_zones ON j_zones.id = items.zone_id
LEFT JOIN 
    roles_zones ON roles_zones.zone_id = j_zones.id
LEFT JOIN 
    roles as z_roles ON (z_roles.id = roles_zones.role_id)
LEFT JOIN 
    items_roles ON items_roles.item_id = items.id
LEFT JOIN 
    roles as i_roles ON items_roles.role_id = i_roles.id
                     AND (z_roles.role_type_id = i_roles.role_type_id)
WHERE 
    items.id = 834
GROUP BY
    items.id, z_roles.role_type_id, z_roles.id
ORDER BY 
    i_role_id;

Выглядит правильно:

id  |z_role_type_id |z_role_id |i_role_type_id |i_role_id |
----+---------------+----------+---------------+----------+
834 |5              |111       |5              |68        |
834 |11             |120       |11             |120       |
834 |7              |77        |               |          |
834 |2              |2         |               |          |
834 |12             |91        |               |          |
834 |4              |78        |               |          |
834 |8              |36        |               |          |

А теперь этот запрос:

SELECT
    items.id,
    z_roles.role_type_id as z_role_type_id,
    z_roles.id as z_role_id,
    MAX(i_roles.role_type_id) AS i_role_type_id,
    MAX(i_roles.id) AS i_role_id,
    MAX(CASE
           WHEN (i_roles.role_type_id = 5) THEN i_roles.id
           WHEN (z_roles.role_type_id = 5) THEN z_roles.id
        END) AS role_type_5_value,
    MAX(CASE
           WHEN (i_roles.role_type_id = 11) THEN i_roles.id
           WHEN (z_roles.role_type_id = 11) THEN z_roles.id
        END) AS role_type_11_value,
    MAX(CASE
           WHEN (i_roles.role_type_id = 7) THEN i_roles.id
           WHEN (z_roles.role_type_id = 7) THEN z_roles.id
        END) AS role_type_7_value
FROM 
    items
LEFT JOIN 
    zones AS j_zones ON j_zones.id = items.zone_id
LEFT JOIN 
    roles_zones ON roles_zones.zone_id = j_zones.id
LEFT JOIN 
    roles AS z_roles ON (z_roles.id = roles_zones.role_id)
LEFT JOIN 
    items_roles ON items_roles.item_id = items.id
LEFT JOIN 
    roles AS i_roles ON items_roles.role_id = i_roles.id
                     AND (z_roles.role_type_id = i_roles.role_type_id)
WHERE 
    items.id = 834
GROUP BY 
    items.id,
    z_roles.role_type_id,
    z_roles.id
ORDER BY 
    items.id, i_role_id;

Генерируетэто:

 id  | z_role_type_id | z_role_id | i_role_type_id | i_role_id | role_type_5_value | role_type_11_value | role_type_7_value 
-----+----------------+-----------+----------------+-----------+-------------------+--------------------+-------------------
 834 |              5 |       111 |              5 |        68 |               111 |                    |                  
 834 |             11 |       120 |             11 |       120 |                   |                120 |                  
 834 |              7 |        77 |                |           |                   |                    |                77
 834 |              2 |         2 |                |           |                   |                    |                  
 834 |             12 |        91 |                |           |                   |                    |                  
 834 |              4 |        78 |                |           |                   |                    |                  
 834 |              8 |        36 |                |           |                   |                    |                  
(7 rows)

Несколько строк и неправильное значение для role_type_5_value.Вероятно, из-за агрегатора MAX.Можно ли использовать что-то вроде first агрегатора (потому что строки, упорядоченные по i_role_id и первые результаты верны)?

Я хочу это:

 id  | role_type_5_value | role_type_11_value | role_type_7_value 
-----+-------------------+--------------------+-------------------
 834 |                68 |                120 |                77    

Я пытался group by по агрегированным полям (role_type_5_value, role_type_11_value, role_type_7_value), но это просто не работает.

1 Ответ

0 голосов
/ 19 мая 2018

Во-первых: удаление ненужных таблиц-мостов из основного запроса и сжатие их в EXISTS() условия упростит ваш запрос (вам нужно всего три таблицы, остальные - клей)

Во-вторых: don 'т все ваши условия в пункте GROUP BY.


SELECT
  i0.id
   , MAX(CASE
    WHEN (r1.role_type_id = 5) THEN r1.id
    WHEN (r0.role_type_id = 5) THEN r0.id
  END) AS role_type_5_value
  , MAX(CASE
    WHEN (r1.role_type_id = 11) THEN r1.id
    WHEN (r0.role_type_id = 11) THEN r0.id
  END) AS role_type_11_value
  , MAX(CASE
    WHEN (r1.role_type_id = 7) THEN r1.id
    WHEN (r0.role_type_id = 7) THEN r0.id
  END) AS role_type_7_value

FROM items i0
LEFT JOIN roles AS r0
  ON EXISTS ( SELECT*
        FROM zones AS z0
        JOIN roles_zones rz ON rz.zone_id = z0.id
        WHERE z0.id = i0.zone_id
        AND r0.id = rz.role_id)

LEFT JOIN roles AS r1
  ON EXISTS ( SELECT*
        FROM items_roles ir
        WHERE ir.item_id = i0.id
        AND ir.role_id = r1.id
        AND r0.role_type_id = r1.role_type_id
        )

WHERE i0.id = 834
GROUP BY i0.id
         -- r0.role_type_id,
         -- r0.id
ORDER BY i0.id;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...