Запрос:
Глубина выборки:
Результатов:
Подсчитывать число записей


Код скрипта:

<?php
require_once "config.php";
ob_start("ob_gzhandler");

// Разбираемся с формой.
$mask    = @$_REQUEST['mask'];
$depth   = @$_REQUEST['depth']; 
$num     min(100max(10, @intval($_REQUEST['num']))); 
$doCount = @$_REQUEST['count'];

if (!isset(
$_REQUEST['mask'])) $_REQUEST['mask'] = "/";
if (!isset(
$_REQUEST['depth'])) $_REQUEST['depth'] = 4
if (!isset(
$_REQUEST['count'])) $_REQUEST['count'] = true;
if (!isset(
$_REQUEST['num'])) $_REQUEST['num'] = 100

// Ограничения.
if (!$depth$depth $MAX_NEST;
if (
$depth $MAX_NEST$depth $MAX_NEST;

// Нажали кнопку?
if ($mask) {
  
// Разбиваем путь по "/".
  
$parts explode('/'$mask);
  if (
$parts[count($parts)-1] === ''array_pop($parts);
  
  
// Составляем большой SQL-запрос.
  
$fields = array();  // куски после SELECT (имена полей выборки)
  
$joins = array();   // JOIN-ы
  
$wheres = array();  // WHERE-условия
  
$levels = array();  // инкременты для level
  
for ($i=0$i<$depth$i++) {
    
// Алиасы для таблицы.
    
$alias     =       "t".sprintf("%04d"$i);
    
$aliasPrev $i>0"t".sprintf("%04d"$i-1) : null;
    
// Список полей для конкретного алиаса.
    
$fields[] = join(", ", array(
      
"$alias.id as `$i.id`",
      
"$alias.parent as `$i.parent`",
      
"$alias.text as `$i.text`"
    
));
    
// LEFT JOIN только для второй и далее таблиц!
    
if ($aliasPrev)
      
$joins[] = "LEFT JOIN $TBL_TREE $alias ON ($alias.parent=$aliasPrev.id)";
    else
      
$joins[] = "$TBL_TREE $alias";
    
// Привязываемся к корню (если поиск от корня).
    
if (!$aliasPrev && substr($mask0,1)=='/'$wheres[] = "$alias.parent=0";
    
// Условия поиска.
    
if (isset($parts[$i])) $wheres[] = "$alias.text LIKE '".addslashes($parts[$i])."'";
    
// Инкремент level-а.
    
$levels[] = "IF($alias.id IS NOT NULL,1,0)";
  }

  
// Подсчет общего числа результатов.
  
$t0 explode(" "microtime());
  if (
$doCount) {
    
$sql join("\n", array(
      
"-- rnd: " time(),
      
"SELECT",
        
"\t COUNT(*)",
      
"FROM",
        
"\t" join("\n\t"$joins),
      
"WHERE",
        
"\t" join(" AND \n\t"$wheres),
    ));
    
$result mysql_query($sql) or die(mysql_error().": $sql");
    
$numRows mysql_result($result00);
  } else {
    
$numRows '?';
  }
  
$t1 explode(" "microtime());
  
$deltaTimeC = ($t1[0]+$t1[1]) - ($t0[0]+$t0[1]);

  
// Запрос с LIMIT-ом.
  
$t0 explode(" "microtime());
  
$sql join("\n", array(
    
"-- rnd: " time(),  
    
"SELECT",
      
"\t(" .  join("+"$levels) . ") as level,",
      
"\t" join(",\n\t"$fields),
    
"FROM",
      
"\t" join("\n\t"$joins),
    
"WHERE",
      
"\t" join(" AND \n\t"$wheres),
#    "ORDER BY level DESC" . "\n" .
    
"LIMIT $num"
  
));
  
$result mysql_query($sql) or die(mysql_error().": $sql");
  
$t1 explode(" "microtime());
  
$deltaTimeR = ($t1[0]+$t1[1]) - ($t0[0]+$t0[1]);

  
// Чистим результаты запроса.
  
$nCols 0;
  for (
$rows=array(); $row=mysql_fetch_assoc($result); ) {
    
// Удаляем все поля, кроме level и text.
    
$r = array();
    foreach (
$row as $k=>$v
      if (!
preg_match('/\.(id|parent)$/'$k) || $k == "0.id"
        
$r[$k] = $v;
    
$rows[] = $r;
    
$nCols max($nCols$row['level']);
  }
  
// Удаляем заведомо пустые столбцы.
  
foreach ($rows as $k=>$v) {
    
array_splice($rows[$k], $nCols+2); // +2 - для level и id
  
}
}
?>

<form method="get">
Запрос: <input type="text" name="mask" value="<?=@htmlspecialchars($_REQUEST['mask'])?>"><br>
Глубина выборки: <input type="text" name="depth" value="<?=@htmlspecialchars($_REQUEST['depth'])?>"><br>
Результатов: <input type="text" name="num" value="<?=@htmlspecialchars($_REQUEST['num'])?>"><br>
<input type="checkbox" name="count" <?=@$_REQUEST['count']? 'checked' ''?>> Подсчитывать число записей<br>
<input type="submit" value="Выполнить">
<br>
</form>
<?if (@$rows) {?>
  <hr>
  <p>
    Найдено записей всего: <b><?=$numRows?></b><br>
    Время подсчета числа записей: <b><?=sprintf("%.3f"$deltaTimeC)?></b> с.<br>
    Время получения результата: <b><?=sprintf("%.3f"$deltaTimeR)?></b> с.
  </p>
  <table border="1">
    <tr>
      <td>#</td>
      <?foreach ($rows[0] as $k=>$v) {?>
        <td><b><?=$k?></b></td>
      <?}?>
    </tr>
    <?foreach ($rows as $i=>$row) {?>
      <tr>
        <td><?=$i+1?></td>
        <?foreach ($row as $k=>$v) {?>
          <td><?=htmlspecialchars($v)?><br></td>
        <?}?>
      </tr>
    <?}?>
  </table>
  <p>SQL-запрос:</p>
  <pre><?=$sql?></pre>
<?}?>
<hr>
<p>Код скрипта:</p>
<?show_source(__FILE__)?>