У меня есть две строки данных — всегда только две строки, но может быть максимум около сорока столбцов. Имена столбцов различны в каждом конкретном случае, но вот типичный пример:
id | height | width | colour | in_stock | featured | on_sale
------------------------------------------------------------
1 | 30 | 20 | black | yes | no | yes
2 | 30 | 25 | red | yes | yes | no
Я хочу получить все различия между этими двумя строками в массиве, чтобы я мог записать, что было изменено с строки 1 на строку 2.
Я думал, что array_diff () сделает эту работу!
Так что я радостно бросил на него array_diff ():
//Simplified queries for the example
$sql1 = "SELECT * FROM table WHERE id = 1";
$rs1 = $conn->Execute($sql1);
$rs1 = $rs1->fields;
$sql2 = "SELECT * FROM table WHERE id = 2";
$rs2 = $conn->Execute($sql2);
$rs2 = $rs2->fields;
//Build first array
foreach($rs1 as $key => $value){
$data1[$key] = $value;
}
//Build second array
foreach($rs2 as $key => $value){
$data2[$key] = $value;
}
//Find the differences
$theDifferences = array_diff($data1, $data2);
//Loop through the differences logging the changes
foreach($theDifferences as $field => $value){
echo "Change found for ".$field."!";
}
Почему это не работает
Это «выглядело как» это работало. Поскольку многие столбцы содержат длинные строки, названия цветов, даты и т. Д., Поэтому при изменении одного из них он был должным образом помещен в массив различий. Проблема состояла (конечно) в том, что несколько столбцов «да» или «нет» не вели себя так, как я ожидал. Таким образом, результат кода выше, для примера таблицы:
colour, width
Он не «видит» избранные или on_sale столбцы как измененные, потому что массив data1 И массив data2 оба содержат «нет» и «да».
Я полагаю, мне нужно сравнить по ключу? Что-то вроде противоположности array_diff_key ()? Но здесь я застрял.
Я также подумал, можно ли это сделать исключительно с помощью SQL-запроса, что, как я полагаю, будет более эффективным, но это далеко за пределы моих возможностей SQL.
Заранее спасибо.
Я думаю, что вы почти у цели. Может быть, что-то вроде этого после ваших запросов:
$theDifferences = array();
foreach($rs1 as $key => $value){
if ($rs2[$key] != $value){
$theDifferences[$key] = $value;
}
}
Что касается SQL, вы можете использовать EXCEPT, чтобы получить список строк, которые отличаются между двумя запросами, но вам все равно придется циклически проходить по клавишам и искать нулевые значения — что не спасет вас много.
Других решений пока нет …