MySQL выбирает недостающие строки

У меня есть таблица с информацией о пользователе:

    user_id | meta_key | meta_value
 -----------+----------+-------------
      1     | name     | John
      1     | surname  | Doe
      2     | name     | Luke
      3     | name     | Jane

Я хочу выбрать строки с определенным ключом, учитывая список идентификаторов.

If I do:

SELECT meta_value FROM table WHERE meta_key = 'surname' AND user_id IN(1,2,3)

MySQL вернет информацию только для пользователя 1, поскольку у остальных нет фамилии.

Я хотел бы построить запрос, чтобы возвращать точное количество строк в качестве переданных идентификаторов с NULL (или пустой строкой), если у этого конкретного пользователя нет фамилии в таблице.

Я пытался использовать IFNULL(meta_value, ""), а также использовать IF, но это не помогает.

Какие-либо предложения? Я уверен, что это тривиальная вещь, но я не могу обойти эту проблему.

Вот SQLfiddle, показывающий проблему: http://sqlfiddle.com/#!9/86eef2/6< /а>

Мой ожидаемый результат будет:

Doe
NULL
NULL

person nico    schedule 21.09.2015    source источник
comment
Попробуйте meta_value НЕ NULL.   -  person Juan Ruiz de Castilla    schedule 22.09.2015
comment
@nico Это stackoverflow.com/questions/19335787/ любая помощь?   -  person rlb.usa    schedule 22.09.2015
comment
@JuanRuizdeCastilla, но я хочу, чтобы строки, в которых meta_value имеет значение NULL, исключали их, не так ли?   -  person nico    schedule 22.09.2015
comment
@rlb.usa как бы... пытаюсь использовать CASE, но, должно быть, что-то упускаю...   -  person nico    schedule 22.09.2015
comment
@nico Я чувствую, что вы могли бы получить более быструю помощь, если бы использовали что-то вроде sqlfiddle   -  person rlb.usa    schedule 22.09.2015
comment
@rlb.usa ну вот! :)   -  person nico    schedule 22.09.2015
comment
@nico как насчет такого заявления CASE? sqlfiddle.com/#!9/86eef2/10 Обратите внимание, что WHERE meta_key переместился в CASE сейчас. Я уверен, что можно использовать более короткие операторы, но в учебных целях мне нравится демонстрировать CASE, тем более, что это только фрагмент того, что вы на самом деле делаете, и, вероятно, его нужно будет расширить.   -  person rlb.usa    schedule 22.09.2015
comment
@rlb.usa проблема в том, что у каждого user_id будет несколько записей, и мне нужно получить только одну для каждого идентификатора, поэтому в этом случае мне нужно 3 строки, а ваш запрос возвращает 4.   -  person nico    schedule 22.09.2015


Ответы (1)


Попробуйте этот запрос:

SELECT DISTINCT user_id,
(SELECT meta_value FROM mytable B WHERE B.user_id = mytable.user_id AND META_KEY = 'surname') AS 'surname_meta_value'
FROM mytable
WHERE user_id IN(1,2,3)

В учебных целях это может быть более быстрый вариант, в большинстве случаев основанный на решении rlb.usa:

SELECT user_id, 
GROUP_CONCAT(
(CASE WHEN meta_key = "surname" 
    THEN meta_value
    ELSE '' 
END) SEPARATOR '')
AS 'surname_meta_value'
FROM mytable WHERE user_id IN(1,2,3)
GROUP BY user_id
person Juan Ruiz de Castilla    schedule 21.09.2015
comment
Это еще одна возможность, но она имеет O(n^2) время выполнения, которое может быть дорогим или нет! На самом деле зависит от того, сколько данных у OP и насколько быстро это должно быть. - person rlb.usa; 22.09.2015
comment
Я собираюсь попробовать это на своих реальных данных и дам вам знать - person nico; 22.09.2015
comment
@ rlb.usa, я не уверен, если этот второй вариант быстрее с большим количеством данных, не могли бы вы проверить это. - person Juan Ruiz de Castilla; 22.09.2015
comment
@JuanRuizdeCastilla Да, это будет быстрее, это среда выполнения O(n), поскольку для каждой строки не требуется новый запрос. :) - person rlb.usa; 22.09.2015
comment
Второй вариант действительно в 30+ раз быстрее на моей реальной БД! - person nico; 22.09.2015