#mysql #wordpress #advanced-custom-fields #acfpro
#mysql #wordpress #advanced-custom-fields #acfpro
Вопрос:
Я работаю над сайтом WordPress, который использует плагин Advanced Custom Field и плагин Advanced Custom Field repeater, поэтому я не могу изменить структуру базы данных.
Пользовательские поля (и их значения) для каждого сообщения хранятся в таблице, вызываемой post_meta
со следующими полями:
meta_id (autoincrement), post_id, meta_key, meta_value
Для обычных пользовательских полей это просто. Допустим, сообщение 200 имеет «John Doe» для поля «full_name», тогда оно будет сохранено следующим образом:
xxx, 200, full_name, John Doe
Проблема в том, что когда поле содержит подмножество повторяющихся полей, способ его хранения немного сложнее. Для meta_key
, значение равно {fieldName}_{rowNumber}_{subfieldName}
.
Например, в этом WordPress я пытаюсь сохранить игроков команды, которые участвуют в определенном матче, и сколько минут они сыграли в этом матче (вот скриншот):
Вызывается общее поле planilla
(таблица игроков), поэтому каждое значение сохраняется следующим образом:
planilla_1_jugador
, planilla_1_minutos
(идентификатор игрока и минуты, сыгранные для первой строки)
Итак, моя проблема начинается, когда я хочу подсчитать все матчи, сыгранные игроком.Я мог бы посчитать все строки в post_meta
where meta_value
is my player id, но это будет учитывать матчи, в которых игрок играл 0 минут (а я не хочу). Кстати, это запрос, который это делает:
SELECT COUNT(*) as total from $wpdb->postmeta INNER JOIN $wpdb->posts ON ( $wpdb->posts.ID = $wpdb->postmeta.post_id ) WHERE( $wpdb->postmeta.meta_key LIKE 'planilla_%_jugador' AND $wpdb->postmeta.meta_value = {player_id} ) AND $wpdb->posts.post_type = 'partido' AND (($wpdb->posts.post_status = 'publish'))
Если я хочу проверить количество сыгранных минут, мне нужно будет добавить соединение, которое соответствует той же позиции в таблице игроков ( planilla
). Если бы в таблице был дополнительный столбец с именем meta_key_index, в котором хранилось бы число, это было бы так же просто, как это:
SELECT COUNT(*) as total from wp_postmeta pm1 INNER JOIN wp_posts ON ( wp_posts.ID = pm1.post_id )
INNER JOIN wp_postmeta pm2 ON (pm1.post_id = pm2.post_id)
WHERE( pm1.meta_key LIKE 'planilla_%_jugador' AND pm1.meta_value = 420 )
AND (pm2.meta_key LIKE 'planilla_%_minutos_jugados' and pm2.meta_value > 0)
AND (pm1.meta_key_index = pm.meta_key_index)
AND wp_posts.post_type = 'partido' AND ((wp_posts.post_status = 'publish')
Но это не так, поэтому мне нужно выполнить соединение, используя регулярное выражение или что-то в этом роде. Я подумал о нескольких вещах, но, похоже, ничто не позволяет работать.
То, что я делаю прямо сейчас, я делаю 20 запросов (максимальное количество игроков на лист), где ключ жестко закодирован, поэтому вместо того, чтобы делать planilla_%_jugador
, и я запрашиваю planilla_1_jugador
, и так далее, а затем суммирую все результаты в конце. Но 20 запросов выполняются медленно, и я бы предпочел решить все, выполнив только один запрос.
Я надеюсь, что этот пост имеет смысл и заранее благодарен.
Комментарии:
1. Действительно ли нет вариантов для нормализации?
2. Я пытаюсь это сделать. Когда совпадение сохранено, вычислите это число для выбранных игроков и обновите его в базе данных. Но сначала мне нужно обновить для всех игроков, уже загруженных в БД, и выполнение этого таким образом — это то, что занимает много времени.