БлогNot. Небольшой патчик при связи "многие ко многим" в движке (PHP)

Небольшой патчик при связи "многие ко многим" в движке (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 [9885 просмотров]


теги: программирование php mysql время cms патч

К этой статье пока нет комментариев, Ваш будет первым