在我的网页上,有一个名为$submission
的变量。我想从下面的查询中精确显示11行:$submission
等于$row["title"]
的行,高于它的5行,以及它下面的5行。全部按points
降序排列。
我该怎么做?
$sqlStr = "SELECT title, points, submissionid
FROM submission
ORDER BY points DESC";
$result = mysql_query($sqlStr);
$arr = array();
$count=1;
echo "<table class=\"samplesrec\">";
while ($row = mysql_fetch_array($result)) {
echo '<tr >';
echo '<td>'.$count++.'.</td>';
echo '<td class="sitename1">'.$row["title"].'</td>';
echo '<td class="sitename2"><div class="pointlink2">'.number_format($row["points"]).'</div></td>';
echo '</tr>';
}
echo "</table>";
答案 0 :(得分:3)
如果几行共享“点”的相同值,这有点棘手:
points | title | submissionid
------ + ----- + ------------
...
50 | 'foo' | ABCD01234 <-- If (50, 'foo') is the "midpoint" record,
50 | 'bar' | EF7654321 <-- does (50, 'bar') come before or after?
...
在这种情况下,我们需要下订单。为方便起见,我们将按“点数”降序排列,然后按“标题”降序排序。
假设您的“中点记录”的分值为“@points”且标题为“@title”,我们会说“中间点”之前的记录是那些(点,标题)&gt;的记录。 (@points,@ title)。类似地,那些“在”中点之后的记录具有它们(点,标题)&lt; (@points,@ title)。
把它放在一起,我们有:
-- First, initialize user variables with the points and
-- title of our midpoint (including midpoint)
--
SELECT @title := title,
@points := points
FROM submission
WHERE title = ? -- bind your $submission variable bere
LIMIT 1;
-- Now, select six records greater than or equal to our
-- midpoint.
--
SELECT title, points, submissionid
FROM ( SELECT title, points, submissionid
FROM submission
WHERE (points, title) >= (@points, @title)
ORDER BY points ASC, title ASC
LIMIT 6) gte
-- and UNION those records with five records less than
-- our midpoint
--
UNION
SELECT title, points, submissionid
FROM ( SELECT title, points, submissionid
FROM submission
WHERE (points, title) < (@points, @title)
ORDER BY points DESC, title DESC
LIMIT 5) lt
-- Finally sort the result set
--
ORDER BY points DESC, title DESC
答案 1 :(得分:2)
您需要使用UNION
(
SELECT title, points, submissionid
FROM submission
WHERE points < (SELECT points FROM submission WHERE title = <row_title> LIMIT 1)
ORDER BY points DESC LIMIT 5
)UNION(
SELECT title, points, submissionid
FROM submission
WHERE points > (SELECT points FROM submission WHERE title = <row_title> LIMIT 1)
ORDER BY points ASC LIMIT 5
) ORDER BY points DESC
我还没有测试过,但这是它的要点。您将获得10条记录(或更少),您必须在PHP中弄清楚哪些记录应该高于您的$submission
以及下面的记录,因为如果您获得9条记录,您将不知道4条记录是否更高,或者5条记录
或者你可以用2个查询当然&gt; _&gt;
来做答案 2 :(得分:2)
SELECT
title, points, submissionid
FROM
submission
WHERE
ROWID >= (SELECT ROWID FROM submission WHERE ..... ORDER BY points DESC) - 5
AND
ROWID <= (SELECT ROWID FROM submission WHERE ..... ORDER BY points DESC) + 5
ORDER BY
points DESC
答案 3 :(得分:1)
我认为对数据库进行2次查询最简单,但你可以用PHP来完成:
$entryFound = false;
$counter = 0;
$priorEntries = array();
while ($row = mysql_fetch_array($result)) {
$rowHtml = '<tr >';
$rowHtml .= '<td>'.$count++.'.</td>';
$rowHtml .= '<td class="sitename1">'.$row["title"].'</td>';
$rowHtml .= '<td class="sitename2"><div class="pointlink2">'.number_format($row["points"]).'</div></td>';
$rowHtml .= '</tr>';
if ($entryFound) {
if ($counter < 5) {
$counter++;
echo $rowHtml;
}
} else {
array_unshift($priorEntries, $rowHtml);
if (strcmp($row["title"], $submission) == 0) {
echo implode(array_reverse($priorEntries));
$entryFound = true;
}
array_splice($priorEntries, 5);
}
}
答案 4 :(得分:1)
我认为以下可能会做你所要求的。它将运行查询并开始从结果集中读取记录,直到找到标题等于您拥有的$submission
变量的记录的第一个出现(如果我理解它)正确地,您的表的主键是submitid,标题是一个简单的字段 - 即您没有唯一的键,因此可能有多个具有相同标题的记录。)
在找到第一条记录后,它会再读取5条记录并停止。然后它将为您提供您希望打印的记录数组的一部分,最后它将打印出来。
$sqlStr = "SELECT title, points, submissionid FROM submission ORDER BY points DESC";
$result = mysql_query($sqlStr);
$count = 1;
$found = false;
$continue = true;
$records = array();
$row = mysql_fetch_array($result);
while ($row !== false && $continue === true)
{
if($found == false && $row['title'] == $submission)
{
$found = true;
}
elseif($found == true && $count < 6)
{
$count++;
}
elseif($found == true && $count >= 6)
{
$continue = false;
}
$records[] = $row;
$row = mysql_fetch_array($result);
}
if($found === true)
{
if(array_count($records) > 11)
$records = array_splice($records, -11);
}
else
{
$records = array();
}
echo "<table class=\"samplesrec\">";
for($i = 1; $i <= count($records); $i++)
{
echo '<tr >';
echo '<td>'.$i.'.</td>';
echo '<td class="sitename1">'.$records[$i]["title"].'</td>';
echo '<td class="sitename2"><div class="pointlink2">'.number_format($records[$i]["points"]).'</div></td>';
echo '</tr>';
}
echo "</table>";
答案 5 :(得分:1)
如果没有重复的"title"
值,并且没有重复"points"
SELECT title, points, submissionid
FROM submission
WHERE points <=
( SELECT points
FROM submission
WHERE points >=
( SELECT points
FROM submission
WHERE title = @row_title
)
ORDER BY points ASC
LIMIT 1 OFFSET 5
)
ORDER BY points DESC
LIMIT 11 OFFSET 0
答案 6 :(得分:0)
如果打算使用单个查询并且表格很小且性能不重要则使用
SELECT b.title, b.points FROM (
SELECT @rank1 := @rank1 + 1 as slno, temp1.* FROM (
SELECT s1.title, s1.points, COUNT(s2.title) rank
FROM submission s1
JOIN submission s2 ON s1.points <= s2.points
GROUP BY s1.title, s1.points
ORDER BY rank, s1.title ASC
) as temp1
JOIN( SELECT @rank1 := 0 ) AS init
ORDER BY slno
) a
LEFT JOIN (
SELECT @rank2 := @rank2 + 1 as slno, temp1.* FROM (
SELECT s1.title, s1.points, COUNT(s2.title) rank
FROM submission s1
JOIN submission s2 ON s1.points <= s2.points
GROUP BY s1.title, s1.points
ORDER BY rank, s1.title ASC
) as temp1
JOIN( SELECT @rank2 := 0 ) AS init
ORDER BY slno
) b ON a.slno BETWEEN b.slno - 5 AND b.slno + 5
WHERE a.title = <row_title>;
这将返回上面选择的行和最多5行(如果存在)和最多5行(如果存在)。
但是,强烈建议使用临时表来存储排名并使用它来显示排名。
有关上述查询的更多详情@ http://www.artfulsoftware.com/infotree/queries.php?&bw=1280#460
有关优化方法的更多细节@ http://onlamp.com/pub/a/mysql/2007/03/01/optimize-mysql-rank-data.html