使用UNION查询获取while语句的总数

时间:2013-06-23 03:15:49

标签: php mysql mysqli while-loop union

我正在尝试计算用户获得的收入,以便在用户主页上反映,以便他们知道自己推荐的收入。

这是我的代码。

$get_ref_stats = $db->query("SELECT * FROM `members` WHERE `referral` = '".$user_info['username']."'");
$total_cash = 0;
    while($ref_stats = $get_ref_stats->fetch_assoc()){
        $get_ref_cash = $db->query("SELECT * FROM `completed` WHERE `user` = '".$ref_stats['username']."' UNION SELECT * FROM `completed_repeat` WHERE `user` = '".$ref_stats['username']."'");
        $countr_cash = $get_ref_cash->fetch_assoc();
        $total_cash += $countr_cash['cash'];
        $countr_c_rate = $setting_info['ref_rate'] * 0.01;
        $total_cash = $total_cash * $countr_c_rate;
    }

当我刚刚

时它工作正常
$get_ref_cash = $db->query("SELECT * FROM `completed` WHERE `user` = '".$ref_stats['username']."'");

但是只要我在UNION中添加它就不再正确计算了。 例如,completed中有1个条目,completed_repeat中有1个条目,这两个条目的cash条目都为0.75。 $countr_c_rate的变量为0.10,因此$total_cash应该等于0.15,而是显示为0.075,有{和不{}},就好像它不计算其他表一样。< / p>

我希望这是有道理的,因为我不知道如何解释这个问题,但我不确定我在这里做错了什么。

3 个答案:

答案 0 :(得分:2)

在第二个查询而不是UNION中,您应该使用UNION ALL,因为UNION会消除结果集中的重复项。这就是为什么你得到0.075而不是0.15

现在,您不必多次从客户端代码访问数据库,而是在一个查询中更好地计算现金总额。

如果没有看到您的表格结构和示例数据,这可能会有误,但此查询可能看起来像这样

SELECT SUM(cash) cash_total
  FROM
(
    SELECT c.cash 
      FROM completed c JOIN members m
        ON c.user = m.username
     WHERE m.referral = ?
     UNION ALL 
    SELECT r.cash 
      FROM completed_repeat r JOIN members m
        ON r.user = m.username
     WHERE m.referral = ?
) q

如果没有预备语句,您的PHP代码可能看起来像

$sql = "SELECT SUM(cash) cash_total
  FROM
(
    SELECT c.cash
      FROM completed c JOIN members m
        ON c.user = m.username
     WHERE m.referral = '$user_info['username']'
     UNION ALL 
    SELECT r.cash 
      FROM completed_repeat r JOIN members m
        ON r.user = m.username
     WHERE m.referral = '$user_info['username']'
) q";

$result = $db->query($sql);
if(!$result) {
    die($db->error()); // TODO: better error handling
}
if ($row = $result->fetch_assoc()) {
    $total_cash = $row['cash_total'] * $setting_info['ref_rate'];
}

注意事项:在mysqli中使用 prepared statements ,而不是使用连接构建查询。它很容易被sql注入。

答案 1 :(得分:1)

使用$countr_cash = $get_ref_cash->fetch_assoc();,您只需获取结果的第一行。但是,如果你使用UNION,你会得到两行。

因此,您需要迭代所有行以获取所有值。

答案 2 :(得分:1)

好的,所以members表中只有一行。您只在成员表上迭代一次。然后,您尝试使用UNION子句获取行,这将导致两行而不是一行。然后,您只需获取第一行的cash列,并将其添加到$total_cash变量中。

您需要做的是迭代执行UNION查询获得的结果并添加$total_cash变量。这会给你所需的结果。

$get_ref_stats = $db->query("SELECT * FROM `members` WHERE `referral` =  '".$user_info['username']."'");

$total_cash = 0;
while($ref_stats = $get_ref_stats->fetch_assoc()){
    $get_ref_cash = $db->query("SELECT * FROM `completed` WHERE `user` = '".$ref_stats['username']."' UNION SELECT * FROM `completed_repeat` WHERE `user` = '".$ref_stats['username']."'");
    while($countr_cash = $get_ref_cash->fetch_assoc()){
        $total_cash += $countr_cash['cash'];
    }
    $countr_c_rate = $setting_info['ref_rate'] * 0.01;
    $total_cash = $total_cash * $countr_c_rate;
}