如何输出正确的数据库行

时间:2013-02-05 13:21:15

标签: php mysql sql database

我的代码是:

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

每个联盟必须只有一行

1 个答案:

答案 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再次对表格usersvdataalidatausers进行了修改,而不是您在问题中使用的相关子查询。 请注意:我再次加入表users以获取具有alliance = u.allyid但具有不同别名的用户。然后GROUP BY,在同一查询中使用聚合函数。

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


更新1

直接测试针对MySQL的查询,因为您正在使用WAMP。如下面的步骤:

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

enter image description here

  • 从任务栏中打开phpMyAdmin:

enter image description here

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

enter image description here

  • 导航到SQL标签:

enter image description here

  • 在窗口中粘贴您的查询:

enter image description here

  • 然后按“开始”按钮

更新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 Fiddle Demo

这会给你:

| 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_alidataalliances1_users与自己具有相同的字段alliance。不确定这是否正确。


但是你的表格设计存在很大问题。您的表格为normalized

例如,字段TribeAccessGoldSilver似乎是每个用户的相关属性,因此您可以将它们移动到新表类似的东西:

<强> UsersFooProperties

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

字段B1B2B3B4的内容相同,请将其移至新表:

<强> UsersBs

  • UserId
  • B1
  • B2
  • B3

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

<强> Bes

  • BID,
  • 此处有其他属性......

然后:

<强> UsersBs

  • UserId
  • BID
  • 复合键(UseridBID)。

另一个重要问题是这38个字段:friend1,...,friend19friend1wait,...,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的一个例子,这些只是你在这个表中有一些不好的东西的样本,你有其他列,而不是我提到过的。你也必须为其他表做同样的事情。

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