Небольшой патчик при связи "многие ко многим" в движке (PHP)
Есть статьи в таблице notes и теги в таблице tags, связь между ними - многие ко многим, через таблицу cloud, где в записи хранятся id статьи и id связанного с ней тега. Понадобилось расставить теги в порядке добавления (по убыванию значения tags.date).
Большинство тегов были не упорядочены по дате, ведь поле date я добавил в таблицу tags уже на имеющейся базе, заполнив его по умолчанию нулями.
К счастью, информация о датах добавления самих статей хранилась как поле notes.date. Поэтому осталось извлечь все статьи в порядке order by date asc и для каждой из них извлечь все теги, а затем расставить тегам даты, всё время увеличивая величину выставляемого времени модификации тега $dt, всё равно конкретное время не имело значения, а только порядок. Листинг файла:
<? require_once ("functions.php"); title (MAINPAGETITLE); include "header.php"; $dt = time()-100000; $cnt= 0; $sql='select * from notes order by date asc'; $result = dbquery($sql); if ($result && dbrows($result)) { while ($page = dbfetcha($result)) { $id=$page['id']; $sql2='select * from cloud where id_note="'.$id.'"'; $result2 = dbquery($sql2); if ($result2 && dbrows($result2)) { while ($tag = dbfetcha($result2)) { $tid = $tag['id_tag']; $sql3 = 'update tags set date="'.$dt.'" where id="'.$tid.'"'; $result3 = dbquery($sql3); $dt++; $cnt++; } } } } print '<p>Выполнено изменений: '.$cnt.'</p>'; include "footer.php"; ?>
В коде исползьзуется код вида
$dt = time();
так как дата и время хранятся как bigint, я вообще предпочитаю хранить их так, удобно сортировать и несложно потом форматировать, например,
$string=date("d.m.y, H:i", ДАТА_КАК_ЧИСЛО);
В реальном коде делать как в этом примере ни в коем случае нельзя, запрос, вложенный в цикл - это всегда плохо и очень медленно, но мне требовался патчик на 1 раз и объём базы составлял всего несколько сотен записей.
Можно было, наверное, и проще - извлечь все теги, затем для каждого найти самую "младшую" по времени статью, где он встречался (то есть, с самым большим значением даты-времени), затем вписать время этой статьи в качестве времени тега:
<? require_once ("functions.php"); title (MAINPAGETITLE); include "header.php"; $sql='select * from tags'; $result = dbquery($sql); if ($result && dbrows($result)) { $sql='update tags set date=case'; $sql2 =' end where id in ('; $n = dbrows($result); for ($i=0; $i<$n; $i++) { $tag = dbfetcha($result); $id=$tag['id']; $res0=dbquery("select notes.date from notes, cloud where cloud.id_tag = '".$id."'". " and cloud.id_note = notes.id order by notes.date desc limit 0,1"); if ($res0 and dbrows ($res0)) { $note1 = dbfetcha($res0); $date1 = $note1['date']; } else { $date1 = '0'; } print '<br>'.$id.','.$date1; $sql .= ' when id="'.$id.'" then "'.$date1.'"'; $sql2 .= $id; if ($i<$n-1) $sql2.=', '; } $sql2.=')'; $sql.=$sql2; $result = dbquery ($sql); if ($result) print "<p>Выполнено: $sql</p>"; else print "<p>Не выполнено: $sql</p>"; } include "footer.php"; ?>
Выдача будет примерно такой:
//$id, $date1 3,1266710700 4,1266710700 5,1266764700 Выполнено: update tags set date=case when id="3" then "1266710700" when id="4" then "1266710700" when id="5" then "1266764700" end where id in (3, 4, 5)
Последнее - пример запроса, выполняющего изменение по столбцу с разными значениями, вносимыми в разные строки. C select max(notes.date) во вложенном запросе не сработало.
20.02.2010, 16:57 [9950 просмотров]