我的代码是:
public function procAllianceAttRanking($limit="") {
$q = "SELECT " . TB_PREFIX . "users.id userid, " . TB_PREFIX . "users.username username, " . TB_PREFIX . "users.alliance allyid, (
SELECT SUM( " . TB_PREFIX . "vdata.pop )
FROM " . TB_PREFIX . "vdata
WHERE " . TB_PREFIX . "vdata.owner = userid
)totalpop, (
SELECT SUM( " . TB_PREFIX . "alidata.Aap )
FROM " . TB_PREFIX . "alidata
WHERE " . TB_PREFIX . "alidata.id = allyid
)totalpoint, (
SELECT COUNT( " . TB_PREFIX . "users.alliance )
FROM " . TB_PREFIX . "users
WHERE " . TB_PREFIX . "users.alliance = allyid
)totalusers
FROM " . TB_PREFIX . "users
WHERE " . TB_PREFIX . "users.alliance > 0
ORDER BY totalpoint DESC, allyid ASC $limit";
return mysql_query($q);
}
输出代码是这样的:
$sql = $ranking->procAllianceRanking();
$query = mysql_num_rows($sql);
if($query >= 1){
while($row = mysql_fetch_array($sql)){
if($row['allyid'] == $session->alliance) {
echo "<tr class=\"hl\"><td class=\"ra fc\" >".$rank.".</td>";
}else {
echo "<tr class=\"hover\"><td class=\"ra \" >".$rank.".</td>";
}
echo "<td class=\"al \" ><a href=\"allianz.php?aid=".$row['allyid']."\">".$database->getAllianceName($row['allyid'])."</a></td>";
echo "<td class=\"pla \" >".$row['totalusers']."</td>";
echo "<td class=\"av \">".round($row['totalpop']/$row['totalusers'])."</td>";
echo "<td class=\"po lc\">".$row['totalpop']."</td></tr>";
$rank++;
}
}
代码的输出是:
Greatest Alliance
Alliance player Ø points
1. multii 3 4 11
2. multii 3 2 6
3. multii 3 2 6
4. myallianc 2 5 5
5. myallianc 2 1 2
但这不正确! 。在每个联盟的真实travian中只有一行静态,所以我的代码输出是错误的。每个联盟的正确输出必须如下:
Greatest Alliance
Alliance player Ø points
1. multii 3 8 23
2. myallianc 2 6 7
每个联盟必须只有一行
答案 0 :(得分:1)
您的查询应以这种方式编写:
SELECT
u.id userid,
u.username username,
u.alliance allyid,
SUM(v.pop ) AS totalpop,
SUM(a.Aap ) AS totalpoint,
COUNT(ua.alliance ) AS totalusers
FROM users u
INNER JOIN vdata v ON v.owner = u.userid
INNER JOIN alidata a ON a.id = u.allyid
INNER JOIN users ua ON ua.alliance = u.allyid
WHERE users.alliance > 0
GROUP BY u.id,
u.username,
u.alliance
ORDER BY u.totalpoint DESC,
u.allyid ASC ;
我在此查询中所做的工作:
我JOIN
再次对表格users
,vdata
,alidata
和users
进行了修改,而不是您在问题中使用的相关子查询。 请注意:我再次加入表users
以获取具有alliance = u.allyid
但具有不同别名的用户。然后GROUP BY
,在同一查询中使用聚合函数。
如果您想要包含那些未缓存的数据,例如那些在其他表中没有条目的用户,您可能还需要使用LEFT JOIN
而不是INNER JOIN
。
直接测试针对MySQL的查询,因为您正在使用WAMP。如下面的步骤:
请改为尝试:
SELECT
u.id AS userid,
u.username AS username,
u.alliance AS allyid,
SUM(v.pop) AS totalpop,
SUM(a.Aap) AS totalpoint,
COUNT(ua.alliance) AS totalusers
FROM s1_users u
LEFT JOIN s1_vdata v ON v.owner = u.id
LEFT JOIN s1_alidata a ON a.id = u.alliance
LEFT JOIN s1_users ua ON ua.alliance = u.alliance
WHERE u.alliance > 0
GROUP BY u.id,
u.username,
u.alliance;
这会给你:
| USERID | USERNAME | ALLYID | TOTALPOP | TOTALPOINT | TOTALUSERS |
----------------------------------------------------------------------
| 4 | Multihunter | 1 | 18 | 0 | 3 |
| 5 | tester1 | 1 | 33 | 0 | 3 |
| 6 | tester2 | 1 | 18 | 0 | 3 |
请注意:我在allyid
表格中找不到列s1_users
,因此我使用s1_users
加入了表格s1_alidata
列alliance
和s1_users
与自己具有相同的字段alliance
。不确定这是否正确。
但是你的表格设计存在很大问题。您的表格为normalized。
例如,字段Tribe
,Access
,Gold
和Silver
似乎是每个用户的相关属性,因此您可以将它们移动到新表类似的东西:
<强> UsersFooProperties
强>
PropertyId
,UserId
用户表的外键,Tribe
,Access
,Gold
,Silver
,ProertyId
,userid`)。字段B1
,B2
,B3
和B4
的内容相同,请将其移至新表:
<强> UsersBs
强>
UserId
,B1
,B2
,B3
。但是,如果这些B
超过三个并且此B
原型还有其他属性,则可以创建一个新表Bs
:
<强> Bes
强>:
然后:
<强> UsersBs
强>
UserId
,BID
,Userid
,BID
)。另一个重要问题是这38个字段:friend1
,...,friend19
,friend1wait
,...,friend19wait
。
你必须为这样的朋友设一个单独的表:
<强>`UsersFriends:强>
UserId
用户表的外键,FriendID
,WaitOrNot
标志0或1。因为你只有一个专栏友,在这一栏中你可以插入这38列的所有朋友:
UserId FriendId WaitOrNot
1 1 0
1 2 1
1 3 0
...
...
1 19 1
同时尽量避免将多个值存储为逗号分隔的字符串值,就像您在FQUEST
列中所做的那样。像这样为它创建一个新表:
<强> UsersFQUEST
强>
UserID
,FQUESTId
。这只是你如何重新设计你的一个表users
的一个例子,这些只是你在这个表中有一些不好的东西的样本,你有其他列,而不是我提到过的。你也必须为其他表做同样的事情。
有关详细信息,请参阅以下内容: