MySQL: сделать СОЕДИНЕНИЕ на основе регулярного выражения? Возможно ли это?

#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. Я пытаюсь это сделать. Когда совпадение сохранено, вычислите это число для выбранных игроков и обновите его в базе данных. Но сначала мне нужно обновить для всех игроков, уже загруженных в БД, и выполнение этого таким образом — это то, что занимает много времени.