1

我的代码是这样的:

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

对于每个联盟必须只有一行

4

1 回答 1

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,alidatausers再次代替了您在问题中使用的这些相关子查询。请注意:我再次加入该表users以获取那些具有alliance = u.allyid但具有不同别名的用户。然后GROUP BY,在同一个查询中使用聚合函数。

如果您想包含那些未连接的数据,例如那些在其他表中没有条目的用户,您可能还需要使用LEFT JOIN而不是。INNER JOIN


更新 1

直接针对 MySQL 测试查询,因为您使用的是 WAMP。就像在以下步骤中一样:

  • 确保 WAMP 服务器正在运行:

在此处输入图像描述

  • 从任务 par 打开 phpMyAdmin:

在此处输入图像描述

  • 选择您正在使用的数据库:

在此处输入图像描述

  • 导航到 SQL 选项卡:

在此处输入图像描述

  • 将您的查询粘贴到窗口中:

在此处输入图像描述

  • 然后按下按钮 Go。

更新 1

试试这个:

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;

SQL 小提琴演示

这会给你:

| 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_userss1_alidataalliances1_users自身与相同的字段连接起来alliance。不确定这是否正确。


但是你的桌子设计有一个大问题。您的表格已标准化

例如,字段 、 和 似乎是每个Tribe用户的相关属性,因此您可以将它们移动到新表中,例如:AccessGoldSilver

UsersFooProperties

  • PropertyId,
  • UserId用户表的外键,
  • Tribe,
  • Access,
  • Gold,
  • Silver,
  • 复合键( ProertyId, userid`)。

字段B1B2B3也是如此B4,将它们移动到新表中:

UsersBs

  • UserId,
  • B1,
  • B2,
  • B3.

但是,如果这些Bs 超过三个并且此属性还有其他属性B,则可以创建一个新表Bs

Bes

  • 投标,
  • 这里的其他属性...

然后:

UsersBs

  • UserId,
  • BID,
  • 复合键( Userid, BID)。

另一个大问题是这 38 个字段:friend1, ... , friend19, friend1wait, ..., friend19wait

你必须为这样的朋友准备一张单独的桌子:

`用户朋友:

  • UserId用户表的外键,
  • FriendID,
  • WaitOrNot标志 0 或 1。

因为你只有一个列朋友,在这个列中你可以像这样插入这 38 列的所有朋友:

UserId FriendId WaitOrNot
  1       1         0
  1       2         1
  1       3         0
  ...
  ...
  1       19        1

还要尽量避免将多个值存储为逗号分隔的字符串值,就像您在 column 中所做的那样FQUEST。为它创建一个新表,如下所示:

UsersFQUEST

  • UserID,
  • FQUESTId.

这只是一个示例,说明如何重新设计您的一个表,users这些只是您在此表中的一个坏事示例,除了我提到的这些列之外,您还有其他列。您还必须对其他表执行相同的操作。

有关详细信息,请参阅以下内容:

于 2013-02-05T13:27:36.123 回答