Как улучшить SQL, объединяющий одну и ту же таблицу несколько раз - PullRequest
0 голосов
/ 08 апреля 2019

Я поддерживаю проект, использующий MYSQL и PHP, и обнаружил, что структура базы данных выглядит следующим образом.

table user

+----+-------+
| id | name  |
+----+-------+
|  1 | Tom   |
|  2 | John  |
|  3 | Peter |
|  4 | Mary  |
+----+-------+

table data

+--------+----------+----------+
| userid |   type   | content  |
+--------+----------+----------+
|      1 | gender   | male     |
|      1 | comment  | Hello    |
|      1 | phone    | 12345678 |
|      1 | username | tom      |
|    ... | ...      | ...      |
+--------+----------+----------+

Мне нужно написать SQL, чтобы получить данные, подобные этим

+-----+------+--------+----------+---------+----------+
| id  | name | gender |  phone   | comment | username |
+-----+------+--------+----------+---------+----------+
|   1 | Tom  | male   | 12345678 | Hello   | tom      |
| ... | ...  | ...    |      ... | ...     | ...      |
+-----+------+--------+----------+---------+----------+

Так что SQL будет

SELECT user.id as "id",user.name as "name",d1.content as 'gender', d2....... FROM user
LEFT JOIN data d1 on d1.userid = user.id and d1.type = 'gender'....
LEFT JOIN...
LEFT JOIN...
LEFT JOIN...

Это работает, но я думаю, что это слишком сложно и сложно для обслуживания. Производительность также не очень хорошая. Также, когда я добавляю больше типов в таблицу data, мне нужно добавить больше join ко всем запросам.

Если SQL уже извлекает данные из таблицы data, сможет ли он отфильтровать его, и нет необходимости присоединять его снова?

Любая идея, чтобы сделать мой запрос SQL проще и быстрее?

1 Ответ

2 голосов
/ 08 апреля 2019

Другой способ сделать это с условным агрегированием:

SELECT u.id,
       MAX(CASE WHEN d.type = 'gender' THEN content END) AS gender,
       MAX(CASE WHEN d.type = 'comment' THEN content END) AS comment,
       MAX(CASE WHEN d.type = 'phone' THEN content END) AS phone,
       MAX(CASE WHEN d.type = 'username' THEN content END) AS username
FROM user u
LEFT JOIN data d ON d.userid = u.id
WHERE u.id = 1
GROUP BY u.id

Вывод:

id  gender  comment phone       username
1   male    Hello   12345678    tom

Демонстрация на dbfiddle

...