Как имитировать операцию SQL LEFT JOIN с использованием массивов PHP?

У меня есть приложение, которое подключается к нескольким серверам. где один сервер будет иметь идентификатор, который является внешним ключом для таблицы, расположенной на другом сервере. Проблема здесь в том, что MySQL не поддерживает связанные серверы, поэтому я не могу запустить левый запрос, который LEFT объединит 2 таблицы, расположенные на разных серверах.

Поэтому мне нужно вытащить 2 отдельных запроса с 2 разных серверов, используя PHP, и они LEFT JOINing их используют PHP.

Обратите внимание, что перечисленные ниже ключи массива должны быть динамическими. Я не могу использовать фиксированные имена, так как разные запросы будут иметь другое имя столбца. В приведенном ниже примере используется phone_call_id в качестве ключа для соединения обоих массивов, и он объединяет имя столбца. если $right_array имеет больше столбцов, то эти столбцы необходимо добавить в окончательный массив.

поэтому у меня есть 2 массива

$left_array = 
Array
(
    [0] => Array
        (
            [id] => 1
            [start_on] => 2014-09-14 19:50:00
            [end_on] => 2014-09-14 19:51:00
            [subject] => This is a new event
            [client_id] => 
            [all_day_event] => 0
            [event_type] => Event
            [phone_call_id] => 122
        )

    [1] => Array
        (
            [id] => 2
            [start_on] => 2014-09-15 05:53:00
            [end_on] => 2014-09-15 06:53:00
            [subject] => This is a new event
            [client_id] => 
            [all_day_event] => 0
            [event_type] => Event
            [phone_call_id] => 123
        )

    [2] => Array
        (
            [id] => 3
            [start_on] => 2014-09-15 05:53:00
            [end_on] => 2014-09-15 06:53:00
            [subject] => This is a new event
            [client_id] => 
            [all_day_event] => 0
            [event_type] => Event
            [phone_call_id] => 
        )
)

Правильный массив будет выглядеть так

$right_array = 
Array
(
    [0] => Array
        (
            [account_id] => 1
            [phone_call_id] => 122
        )

    [1] => Array
        (
            [account_id] => 2
            [phone_call_id] => 123
        )
)

результаты должны быть похожи на этот массив

$joined_array = 
Array
(
    [0] => Array
        (
            [id] => 1
            [start_on] => 2014-09-14 19:50:00
            [end_on] => 2014-09-14 19:51:00
            [subject] => This is a new event
            [client_id] => 
            [all_day_event] => 0
            [event_type] => Event
            [phone_call_id] => 122
            [account_id] => 1
        )

    [1] => Array
        (
            [id] => 2
            [start_on] => 2014-09-15 05:53:00
            [end_on] => 2014-09-15 06:53:00
            [subject] => This is a new event
            [client_id] => 
            [all_day_event] => 0
            [event_type] => Event
            [phone_call_id] => 123
            [account_id] => 2
        )

    [2] => Array
        (
            [id] => 3
            [start_on] => 2014-09-15 05:53:00
            [end_on] => 2014-09-15 06:53:00
            [subject] => This is a new event
            [client_id] => 
            [all_day_event] => 0
            [event_type] => Event
            [phone_call_id] => 
            [account_id] =>

        )
)

person Jaylen    schedule 14.09.2014    source источник
comment
вы можете посмотреть на этот ответ PHP ARRAY JOIN   -  person Erdal CEYLAN    schedule 26.10.2017


Ответы (7)


Эта функция имитирует операцию левого соединения

   //function to simulate the left join
    function left_join_array($left, $right, $left_join_on, $right_join_on = NULL){
        $final= array();

        if(empty($right_join_on))
            $right_join_on = $left_join_on;

        foreach($left AS $k => $v){
            $final[$k] = $v;
            foreach($right AS $kk => $vv){
                if($v[$left_join_on] == $vv[$right_join_on]){
                    foreach($vv AS $key => $val)
                        $final[$k][$key] = $val; 
                } else {
                    foreach($vv AS $key => $val)
                        $final[$k][$key] = NULL;            
                }
            }
        }
       return $final;
    }

//функцию можно использовать таким образом, предполагая, что имя столбца в левом массиве такое же, как и в правом массиве

$final_array = left_join_array($left, $right, 'phone_call_id');

//функцию можно использовать таким образом, предполагая, что имя столбца в левом массиве «различно, но имеет одинаковое соответствующее значение»

$final_array = left_join_array($left, $right, 'phone_call_id', 'p_c_id');
person Jaylen    schedule 14.09.2014

привет Вы можете попробовать этот фрагмент кода, это даст вам объединенный массив, похожий на левое внешнее соединение:

foreach($left_array as $k => $v){
   foreach($right_array as $kk => $vv){
     if($v['id'] == $vv['account_id']){
         foreach($vv as $key => $val){
             $left_array[$k]['right_'.$key] = $val; 
         }
     }
   }
}

вы получите поля из правого массива с префиксом "right_"

person Pulkit    schedule 14.09.2014
comment
Привет, я взял ваш код, немного изменил его, чтобы он соответствовал моим потребностям. но проблема, с которой я сталкиваюсь сейчас, заключается в том, что, когда phone_call_id имеет значение null, у меня будет отсутствующая ячейка в массиве. Я помещу код, который у меня есть в настоящее время, в свой пост, чтобы вы могли взглянуть на него. - person Jaylen; 14.09.2014
comment
Извините, кажется, я не понял, что вы пытаетесь сказать. Согласно логике, если какое-то поле пустое или пустое, оно вернет только одно и то же, верно? Пожалуйста, введите свой код. Я проверю это и постараюсь дать подходящий ответ. :) - person Pulkit; 14.09.2014
comment
Я исправил функцию и опубликовал ее как ответ, чтобы помочь другим. спасибо, что дали мне необходимые хиты, чтобы решить проблему - person Jaylen; 14.09.2014

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

на случай, если я снова столкнусь с той же проблемой, я опубликую это здесь

Сценарий, который у меня есть, такой:

сценарий

Когда я использую принятый ответ здесь, я получаю что-то вроде этого:

//function to simulate the left join
function left_join_array($left, $right, $left_join_on, $right_join_on = NULL){
    $final= array();

    if(empty($right_join_on))
        $right_join_on = $left_join_on;

    foreach($left AS $k => $v){
        $final[$k] = $v;
        foreach($right AS $kk => $vv){
            if($v[$left_join_on] == $vv[$right_join_on]){
                foreach($vv AS $key => $val)
                    $final[$k][$key] = $val; 
            } else {
                foreach($vv AS $key => $val)
                    $final[$k][$key] = NULL;            
            }
        }
    }
   return $final;
}

неправильный_результат

Это не тот результат, которого я хотел, потому что все равно null, хотя в правой таблице есть совпадающие данные, и это произошло потому, что следующая итерация foreach заменяет правильное значение на null.

Что я делаю, так это добавляю break к последнему foreach, а также добавляю префикс к добавленному значению, чтобы избежать замены левой таблицы (на всякий случай, на случай, если у меня есть столбец с одинаковым именем между таблицами)

//function to simulate the left join
function left_join_array($left, $right, $left_join_on, $right_join_on = NULL)
{
  $final = array();

  if (empty($right_join_on))
    $right_join_on = $left_join_on;

  foreach ($left as $k => $v) {
    $final[$k] = $v;
    foreach ($right as $kk => $vv) {
      if ($v[$left_join_on] == $vv[$right_join_on]) {
        foreach ($vv as $key => $val)
          $final[$k]['_' . $key] = $val; /* add prefix on the key */
        break; /* add break here */
      } else {
        foreach ($vv as $key => $val)
          $final[$k]['_' . $key] = NULL; /* add prefix on the key */
      }
    }
  }
  return $final;
}

желаемый результат

и это желаемый результат для меня.

person Bharga Wiguna    schedule 22.10.2020

Попробуйте это (при условии, что ваши пустые значения «phone_call_id» и «accout_id» равны нулю):

$joined_array = array();
foreach($right_array as $right_row){
    $phone_call_id = $right_row['phone_call_id'];
    $account_id    = $right_row['account_id'];
    foreach($left_array as $i => $left_row){
        if($left_row['phone_call_id'] === $phone_call_id){
            $left_row['account_id'] = $account_id;
            $joined_array[]         = $left_row;
        }
    }
}
//And here, we have to identify rows with empty 'phone_call_id'
foreach($left_array as $left_row){
    if($left_row['phone_call_id'] === null){
        $left_row['account_id'] = null;
        $joined_array[]         = $left_row;
    }
}
person Facundo Fasciolo    schedule 14.09.2014

простое решение,

работал на меня, используйте это,

function arrayLeftJoin($left,$right){
    foreach ($left as $lkey => $lvalue) {
        foreach ($right as $rkey => $rvalue) {
            if($lkey==$rkey){
                unset($left[$lkey]);
            }
        }
    }
    return $left;
}

Спасибо всем

person Dhanu K    schedule 20.01.2018

Старайтесь избегать подобных операций. Если можете, попробуйте разместить все базы данных на одном сервере и использовать SQL JOIN-s. PHP — это не MYSQL. PHP не предназначен для (левых, правых и т. д.) таблиц соединения. например если у вас есть огромное количество записей в левой таблице, возвращаемых mysql и помещаемых в результате в массив, вы можете столкнуться с большими проблемами с памятью. Выполняйте задания MYSQL, используя MYSQL, выполняйте задания PHP, используя PHP. Так вы сэкономите: время, выступления и нейроны. :)

person Levac Onlajn    schedule 11.05.2018
comment
А что, если вы работаете с распределенной системой, в которой есть таблицы на разных серверах? - person Renan Cavalieri; 05.07.2018
comment
Вы можете сказать, что в этом случае у вас проблемы. :( В этом случае вам придется использовать PHP для моделирования JOIN... Однако вы очень скоро столкнетесь с проблемами, которые я описал ранее. Особенно в случаях LEFT JOIN над таблицами, которые содержат очень много строк (если у вас есть такие таблицы ) В некоторых случаях вы можете столкнуться с проблемами, которые не могут быть решены. - person Levac Onlajn; 10.07.2018

Хорошо, старая тема, но мы никогда не знаем ... может быть полезной. Просто небольшое обновление решения Jaylen.

function left_join_array($left, $right, $left_join_on, $right_join_on = NULL){
     $final= array();

     if(empty($right_join_on))
         $right_join_on = $left_join_on;

     foreach($left AS $k => $v){
         $final[$k] = $v;
         foreach($right AS $kk => $vv){
             if($v[$left_join_on] === $vv[$right_join_on] ){
                 foreach($vv AS $key => $val)
                     $final[$k][$key] = $val; 
             } else if(!isset($final[$k][$right_join_on])) {
                 foreach($vv AS $key => $val)
                     $final[$k][$key] = NULL;            
             }
         }
     }
    return $final;
 }
person genio    schedule 25.09.2020