2013-12-04 3 views
0

Мне нужна помощь .. Мне нужно вывести значение DisplayName, если значение fullname возвращает нулевой или пустой как FullName.SQL Выберите, если else

что-то вроде

if(u.first_name && u.last_name are not empty) 
    output CONCAT(u.first_name,' ',u.last_name) 
else 
    output max(case when t.field_id = 1 then t.value else '' end) 

, но как? Также мой запрос занял 3,45 секунд :(..

SELECT * FROM( 
    SELECT 
      t.user_id, 

##this code
макс (случай, когда t.field_id = 1, то t.value еще '' конец) DisplayName,
CONCAT (u.first_name, '', u.last_name) ПолноеИмя,

  max(case when t.field_id = 270 then t.value else '' end) Gender, 
      max(case when t.field_id = 274 then t.value else '' end) Birthday, 
      max(case when t.field_id = 274 then FLOOR(DATEDIFF(CURRENT_DATE, STR_TO_DATE(t.value,'%m/%d/%Y'))/365) else '' end) Age, 
      max(case when t.field_id = 275 then t.value else '' end) Phone, 
      max(case when t.field_id = 286 then t.value else '' end) Email, 
      max(case when t.field_id = 71 then t.value else '' end) Occupation, 
      max(case when t.field_id = 73 then t.value else '' end) CurrentCountry, 
      max(case when t.field_id = 24 then t.value else '' end) Region, 
      max(case when t.field_id = 355 then t.value else '' end) Province, 
      max(case when t.field_id = 354 then t.value else '' end) City 
    FROM wp_bp_xprofile_data t 
    LEFT JOIN (
     SELECT 
     user_id id, 
     max(case when meta_key = 'first_name' then meta_value end) first_name, 
     max(case when meta_key = 'last_name' then meta_value end) last_name 
     from wp_usermeta 
     GRoup by user_id 

    )as u 
    ON u.id = t.user_id 
    GROUP BY user_id 
)temp 
WHERE 1 = 1 
##Some Condition to be added 
LIMIT 0 , 30 
+0

это Mysql RDBMS? –

+0

yes.its mysql .. – Cindy93

+0

CONCAT (IFNULL (u.first_name, ''), '', IFNULL (u.last_name, '')) FullName, – realnumber3012

ответ

1

Я бы несколько раз переходил на несколько соединений в одну и ту же таблицу, чтобы получить каждое поле по своим собственным критериям как возможность производительности. Запустите данные профиля один, скажем, field_id = 1 в качестве основы, , затем присоедините все остальное на том же ключе, а затем не группируйте по или макс/случай, если на каждой проверенной строке. Если некоторые поля НЕ могут существовать, просто используйте LEFT-JOIN для повторно используемой таблицы с альтернативным псевдонимом. Я бы обеспечить вам/охватывающую индекс соединения на вашем профиле таблицы со следующим ключом

(user_id, FIELD_ID, значение)

Затем сделать следующий запрос. Интересная вещь здесь заключается в том, что она в основном открывает одну и ту же таблицу для каждой «компонентной» части user_ID и выстраивает их все в очередь, но запускает запрос, основанный только на одном экземпляре записей, связанных с field_id = 1 в предложении where. Все остальные экземпляры находятся в их соответствующих псевдонимах, связанных с предложением ON. Итак, теперь я просто запускаю записи для field_id = 1, и если их можно найти в других таблицах, захватывает значение, в противном случае - пустое (через coalesce). Аналогично соединен с таблицей метаданных пользователя, чтобы получить части первого и последнего имени.

Если это сработает для вас, мне было бы интересно узнать о производительности в одну или другую сторону. Преимущество в том, что ему не нужно запрашивать EVERYONE спереди (самый внутренний запрос), чтобы затем запустить основной запрос всех записей, применить группу, а затем остановиться в своем 30-ом пределе. Он просто добирается до первых 30, где field_id = 1 и его делается. Теперь, если население «field_id = 1» является малонаселенным полем, и вы хотите поменять его на другой, пусть так, вы знаете свои данные лучше нас.

SELECT 
     DN.User_ID, 
     case when fn.user_id is null and ln.user_id is null then DN.value 
      when fn.user_id is null then ln.meta_value 
      when ln.user_id is null then fn.meta_value 
      else concat(fn.meta_value, ' ', ln.meta_value) end as FinalName, 
     DN.Value DisplayName, 
     CONCAT(COALESCE(fn.meta_value, ''),' ',COALESCE(ln.meta_value, '')) FullName, 
     COALESCE(G.Value, '') Gender, 
     COALESCE(BD.Value, '') Birthday, 
     COALESCE(FLOOR(DATEDIFF(CURRENT_DATE, STR_TO_DATE(BD.value,'%m/%d/%Y'))/365), '') Age, 
     COALESCE(P.Value, '') Phone, 
     COALESCE(E.Value, '') Email, 
     COALESCE(O.Value, '') Occupation, 
     COALESCE(CC.Value, '') CurrentCountry, 
     COALESCE(R.Value, '') Region, 
     COALESCE(PR.Value, '') Province, 
     COALESCE(C.Value, '') City 
    from 
     wp_bp_xprofile_data DN 
     LEFT JOIN wp_bp_xprofile_data G 
      ON DN.User_ID = G.User_ID AND G.field_id = 270 
     LEFT JOIN wp_bp_xprofile_data BD 
      ON DN.User_ID = BD.User_ID AND BD.field_id = 274 
     LEFT JOIN wp_bp_xprofile_data P 
      ON DN.User_ID = P.User_ID AND P.field_id = 275 
     LEFT JOIN wp_bp_xprofile_data E 
      ON DN.User_ID = E.User_ID AND E.field_id = 286 
     LEFT JOIN wp_bp_xprofile_data O 
      ON DN.User_ID = O.User_ID AND O.field_id = 71 
     LEFT JOIN wp_bp_xprofile_data CC 
      ON DN.User_ID = CC.User_ID AND CC.field_id = 73 
     LEFT JOIN wp_bp_xprofile_data R 
      ON DN.User_ID = R.User_ID AND R.field_id = 24 
     LEFT JOIN wp_bp_xprofile_data PR 
      ON DN.User_ID = PR.User_ID AND PR.field_id = 355 
     LEFT JOIN wp_bp_xprofile_data C 
      ON DN.User_ID = C.User_ID AND C.field_id = 354 
     LEFT JOIN wp_usermeta FN 
      ON DN.User_ID = FN.User_ID AND FN.meta_key = 'first_name' 
     LEFT JOIN wp_usermeta LN 
      ON DN.User_ID = LN.User_ID AND LN.meta_key = 'last_name' 
    where 
      DN.field_id = 1 
     AND O.Value like '%Programmer%' 
    LIMIT 
     0, 30 

Я изменил, чтобы добавить ФИНАЛЬНОЕ имя, используя случай/когда. , если оба псевдонима FN/LN (имя/фамилия) BOTH null, затем получите значение DN (отображаемое имя). В противном случае у нас есть ОТ МЕНЬШЕ ОДНОГО или ОБОИХ частей первого/последнего поля. Если первое имя было нулевым, просто верните фамилию. Если фамилия была пустой, верните первое имя, иначе BOTH были доступны первые и последние имена, и возвратите конкатенированную версию имени.

Что касается применения дополнительных предложений WHERE. Как только вы добавите «требуемые» критерии в предложение where к любому из псевдонимов с левым соединением, это приведет к их превращению в INNER JOINs и включит только те, которые имеют этот компонент, и этот компонент имеет требуемое значение. .. Итак, за ваш комментарий я бы просто добавил ...

where 
     DN.field_id = 1 
     AND BD.User_ID IS NOT NULL 
     AND STR_TO_DATE(BD.value,'%m/%d/%Y') BETWEEN '2009-01-01' and '2012-01-01' 

Вы можете использовать DATEDIFF по возрасту и сделать это между 1 и 2, но только предпочтением, чтобы выбрать диапазон дат интереса ..

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

LEFT JOIN wp_bp_xprofile_data E 

в

JOIN wp_bp_xprofile_data E 

, если вы хотите, чтобы убедиться, что поле учитывается только если это имеет значение, отличное от пространства (например, вашего последним/имени)

LEFT JOIN wp_usermeta FN 
     ON DN.User_ID = FN.User_ID 
     AND FN.meta_key = 'first_name' 
     AND LENGTH(TRIM(COALESCE(FN.meta_Value, ''))) > 0 

Это будет убедиться, что запись только считается, когда он на самом деле имеет непустое значение строки.

Назад к рассмотрению вопроса «% Programmer%» ... почему бы вам ожидать, что город, провинция, регион и т. Д. Будут иметь значение программиста. Вам потребуется только, чтобы экземпляр занятия имел значение. , потому что вы имели OR, он делает все строки. вы должны были бы обернули условиям что-то вроде

where 
      DN.field_id = 1 
     AND ( O.Value like '%Programmer%' 
      OR E.Value like '%@gmail.com' 
      OR C.Value like 'Some City') 

Обратите внимание, я завернуты мои дополнительные критерии или компоненты. Таким образом, он все еще начинается только с FIELD_ID = 1 запись, но на основе JOIN добавляются дополнительные критерии, и в этом случае DN.field_id = 1 всегда, но ЛЮБОЙ ОДИН (или более) из условий OR также должен быть правдой ... Алиас профессии имеет значение, подобное программист, псевдоним электронной почты имеет значение g mail, псевдоним города, например «Some City».

Надеюсь, это пояснит, как реализовать ... Кроме того, обратите внимание, что использование любого квалификатора LIKE, который имеет «%», ведущий строку, нужно сравнивать по всей строке и замедляет запрос вниз, но поскольку соединение основан на идентификаторе пользователя и значении field_ID, которое должно сохранять его быстрым (относительно).

+0

Спасибо @DRapp. большое улучшение также в производительности. мой запрос заканчивается через 3,45 секунды, а ваш заканчивается 0,0184 секунды. Я думал, что слишком много левого соединения вызовет замедление в sql-запросе. Кстати, LN.meta_value всегда пуст. Я не знаю, почему .. Полное имя возвращает что-то вроде 'John' только тогда, когда оно должно быть' John Doe' И что, если я fil ter это по возрасту «возраст от 1 до 2» - это вопрос в порядке? 'SELECT * FROM (another_sqlquery) ГДЕ возраст от 1 до 2' или есть лучший способ для него? Спасибо – Cindy93

+0

также я попробовал запрос 'SELECT * From wp_usermeta WHERE meta_key = 'last_name'', и все имеет значение .. – Cindy93

+0

@ Cindy93, пересмотренный ответ на добавление дополнительных« критериев »... Что касается фамилии, вы рассматриваете пустое пространство как допустимое значение или явно NULL для значения. – DRapp

0

Попробуйте это:

SELECT if(trim(CONCAT(first_name,' ', lastName))='', 
      DisplayName, 
      CONCAT(first_name,' ', lastName)) as Name 
    ...rest of the fieds on TA subquery 
    FROM ( 
    (SELECT 
     t.user_id, 
     max(case when t.field_id = 1 then t.value else '' end) DisplayName, 
     max(case when t.field_id = 270 then t.value else '' end) Gender, 
     max(case when t.field_id = 274 then t.value else '' end) Birthday, 
     max(case when t.field_id = 274 
      then FLOOR(DATEDIFF(CURRENT_DATE, 
          STR_TO_DATE(t.value, '%m/%d/%Y'))/365) 
      else '' end) Age, 
     max(case when t.field_id = 275 then t.value else '' end) Phone, 
     max(case when t.field_id = 286 then t.value else '' end) Email, 
     max(case when t.field_id = 71 then t.value else '' end) Occupation, 
     max(case when t.field_id = 73 then t.value else '' end) CurrentCountry, 
     max(case when t.field_id = 24 then t.value else '' end) Region, 
     max(case when t.field_id = 355 then t.value else '' end) Province, 
     max(case when t.field_id = 354 then t.value else '' end) City 
    FROM wp_bp_xprofile_data t 
    GROUP BY user_id 
    ) TA 
    LEFT JOIN 
    ( SELECT user_id id, 
       max(case when meta_key = 'first_name' 
        then meta_value end) first_name, 
       max(case when meta_key = 'last_name' 
        then meta_value end) last_name 
      from wp_usermeta 
     GRoup by user_id) as U on (ta.user_id = U.id) 
)temp 
WHERE 1 = 1 
##Some Condition to be added 
LIMIT 0 , 30 
+0

только что обновил мой вопрос .. извините, я сначала не понял – Cindy93

+0

Я сделал именно то, что вы хотите: 'if (trim (CONCAT (first_name, '', LastName)) = '', DisplayName, CONCAT (first_name, '', lastName) как имя' См. If 'trim (CONCAT (first_name, '', LastName)) = '' 'print display, который в подзапросе TA эквивалентен max (case ..., который вы обновляете в своем вопросе, если он не пуст, он будет печатать concat. –

Смежные вопросы