これは phpBB から改変されたコードです。私が知る限り、唯一の投稿者がターゲットユーザーであるすべてのトピックを削除しようとしています。
(テスト目的で、最終クエリを DELETE から SELECT に変更したことに注意してください)
<?php
$user_id = 66275;
mysql_connect('localhost', 'username', 'password');
mysql_select_db('db_name');
$start = microtime(true);
$total = 0;
define('POSTS_TABLE', 'phpbb_posts');
define('TOPICS_TABLE', 'phpbb_topics');
$sql = 'SELECT topic_id, COUNT(post_id) AS total_posts
FROM ' . POSTS_TABLE . "
WHERE poster_id = $user_id
GROUP BY topic_id";
$result = mysql_query($sql);
$topic_id_ary = array();
while ($row = mysql_fetch_assoc($result))
{
$topic_id_ary[$row['topic_id']] = $row['total_posts'];
}
mysql_free_result($result);
if (sizeof($topic_id_ary))
{
$sql = 'SELECT topic_id, topic_replies, topic_replies_real
FROM ' . TOPICS_TABLE . '
WHERE ' . sql_in_set('topic_id', array_keys($topic_id_ary));
$result = mysql_query($sql);
$del_topic_ary = array();
while ($row = mysql_fetch_assoc($result))
{
if (max($row['topic_replies'], $row['topic_replies_real']) + 1 == $topic_id_ary[$row['topic_id']])
{
$del_topic_ary[] = $row['topic_id'];
}
}
mysql_free_result($result);
if (sizeof($del_topic_ary))
{
$sql = 'SELECT topic_id FROM ' . TOPICS_TABLE . '
WHERE ' . sql_in_set('topic_id', $del_topic_ary);
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result))
{
$total++;
echo $row[topic_id] . "\r\n";
}
}
}
function sql_in_set($field, $array, $negate = false, $allow_empty_set = false)
{
if (!sizeof($array))
{
if (!$allow_empty_set)
{
// Print the backtrace to help identifying the location of the problematic code
$this->sql_error('No values specified for SQL IN comparison');
}
else
{
// NOT IN () actually means everything so use a tautology
if ($negate)
{
return '1=1';
}
// IN () actually means nothing so use a contradiction
else
{
return '1=0';
}
}
}
if (!is_array($array))
{
$array = array($array);
}
if (sizeof($array) == 1)
{
@reset($array);
$var = current($array);
return $field . ($negate ? ' <> ' : ' = ') . $var;
}
else
{
return $field . ($negate ? ' NOT IN ' : ' IN ') . '(' . implode(', ', $array) . ')';
}
}
$elapsed = microtime(true) - $start;
echo "\r\ntook $elapsed seconds";
echo "\r\ngot $total rows back";
?>
これは 3 つのクエリを実行します。最初に、対象ユーザーが投稿したすべてのトピックと、各トピックへの投稿回数を取得します。2 番目は、最初のクエリの各トピックが実際に持っている返信の数を取得します。次に、対象ユーザーがすべての投稿を行ったトピックを確認するための PHP コードがあります。その後、コード (私の変更前) はこれらすべてのトピックを削除します。
全体として、これは次のようなことを行うことでより適切に記述できるように思えます。
SELECT t.topic_id
FROM phpbb_topics AS t
JOIN phpbb_posts AS p1
ON p1.topic_id = t.topic_id
AND p1.poster_id = $poster_id
LEFT JOIN phpbb_posts AS p2
ON p2.topic_id = t.topic_id
AND p2.poster_id <> $poster_id
WHERE p2.poster_id IS NULL;
または多分これ:
SELECT t.topic_id
FROM phpbb_topics AS t
JOIN phpbb_posts AS p1
ON p1.topic_id = t.topic_id
AND p1.poster_id = $poster_id
AND t.topic_poster = $poster_id
AND t.topic_last_poster_id = $poster_id
LEFT JOIN phpbb_posts AS p2
ON p2.topic_id = t.topic_id
AND p2.poster_id <> $poster_id
WHERE p2.poster_id IS NULL
これをテストすることは、 MySQL のキャッシングのおかげで実際には非常に困難ですが... 私が実行できたテストから、phpBB が現在行っている方法の方が実際には高速であるように思えます。これは私にとって驚くべきことです。
何か案は?