【问题标题】:MySQL UNION and PHP, not friends?MySQL UNION 和 PHP,不是朋友吗?
【发布时间】:2011-10-14 11:34:03
【问题描述】:

无论我做什么,我都无法将此代码发送给echo $done

这是我的代码的摘录,我无法终生工作。我已经尝试了五种不同的方法,但没有任何效果。我唯一的结论是,由于UNION,它不起作用。

有没有办法解决这个问题?还是这就是问题所在?

$query01 = "SELECT COUNT(DISTINCT report) AS ip 
                FROM reports 
                    WHERE country =  '".$country."' 
                    AND YEAR(date) = '2011' 
                    AND MONTH(date) = '".$i."' AND 
                    status ='IP' 
        UNION
            SELECT COUNT(DISTINCT report) AS done 
                FROM reports 
                    WHERE country =  '".$country."' 
                    AND YEAR(date) = '2011' 
                    AND MONTH(date) = '".$i."' 
                    AND status ='DONE'";

$result01 = mysql_query($query01);

while ($row01 = mysql_fetch_array($result01)) {
    $ip = $row01['ip'];
    $done = $row01['done'];
    $all = $ip + $done;

    if($all>0){
        echo "<td>".$ip.":".$done."</td>";
    }

    else{
        echo "<td>-</td>";
    }

}

【问题讨论】:

  • UNION 将两个选择合并在一起,它不会“加入”它们。在这种情况下,UNION 将仅提供 1 列。
  • 您假设它们是同一行上的两列,但实际上它们是两行。第一行包含ip,第二行包含done
  • 回过头来看这件事,我好像把列和行搞混了。感谢您的所有帮助,朋友们。

标签: php mysql join union


【解决方案1】:

你需要了解的关于 UNION 的事情:

  • UNION 将行附加在一起,它不会将它们作为列并排放置。
  • 列名由 UNION 中的第一个查询确定,不能更改。因此,您的列将命名为 ip,而您在第二个查询中定义的名称 done 将被忽略。

我建议对这个查询使用 GROUP BY 而不是 UNION。然后逐行处理结果。这是一个示例(未经测试):

$query01 = "SELECT status, COUNT(DISTINCT report) AS c
            FROM reports 
            WHERE country = '{$country}' 
              AND date between '2011-{$i}-01' AND '2011-{$i}-32' 
              AND status IN ('IP','DONE')
            GROUP BY status";

$result01 = mysql_query($query01);

$status_count = array("IP"=>0, "DONE"=>0);
while ($row01 = mysql_fetch_array($result01)) {
    $status_count[ $row01["status"] ] = $row01["c"];
}

if (array_sum($status_count) > 0) {
    echo "<td>{$status_count["IP"]}:{$status_count["DONE"]}</td>";
}

else {
    echo "<td>-</td>";
}

【讨论】:

    【解决方案2】:

    您的 UNION 正在合并两个具有不同列的查询:其中一个有一个名为 ip 的列,另一个有一个名为 done 的列。 MySQL 可能正在返回一个名为 ip 的列的结果集,因为这是它遇到的该列的第一个名称。 done 列的值连接到 ip 列的值,但该列已经具有名称 ip。没有名为 done 的列。也许试试:

    $query01 = "SELECT COUNT(DISTINCT report) AS report_count, 'ip' as indicator 
                    FROM reports 
                        WHERE country =  '".$country."' 
                        AND YEAR(date) = '2011' 
                        AND MONTH(date) = '".$i."' AND 
                        status ='IP' 
            UNION
                SELECT COUNT(DISTINCT report) AS report_count, 'done' as indicator 
                    FROM reports 
                        WHERE country =  '".$country."' 
                        AND YEAR(date) = '2011' 
                        AND MONTH(date) = '".$i."' 
                        AND status ='DONE'";
    

    现在两个查询都有相同的列,你可以选择打印indicator = 'done'所在的行。

    【讨论】:

      【解决方案3】:

      我猜您正在尝试将 ipdone 作为每行的两列,在这种情况下 UNION 不是您所拥有的查询的正确选择。

      试试这个:

          $query01 = "SELECT a.ip, b.done 
        FROM 
          (
          SELECT COUNT(DISTINCT report) AS ip 
                          FROM reports 
                              WHERE country =  '".$country."' 
                              AND YEAR(date) = '2011' 
                              AND MONTH(date) = '".$i."' AND 
                              status ='IP' 
              ) a,
              (
                      SELECT COUNT(DISTINCT report) AS done 
                          FROM reports 
                              WHERE country =  '".$country."' 
                              AND YEAR(date) = '2011' 
                              AND MONTH(date) = '".$i."' 
                              AND status ='DONE'
              ) b";
      
          $result01 = mysql_query($query01);
      
          while ($row01 = mysql_fetch_array($result01)) {
              $ip = $row01['ip'];
              $done = $row01['done'];
              $all = $ip + $done;
      
              if($all>0){
                  echo "<td>".$ip.":".$done."</td>";
              }
      
              else{
                  echo "<td>-</td>";
              }
      
          }
      

      【讨论】:

      • 是的,这个工作完美。非常感谢您的澄清!
      【解决方案4】:

      当您执行联合查询时,每个组件中的列数必须匹配(您的),发出的第一个查询中的别名将是列名称将如何返回给客户端(您的脚本)。在您的情况下,您只会有一个 ip 列 - 永远不会有一个 done 列。

      如果您需要区分结果中的每一行来自哪里(哪个组件查询发出的),您可以创建一个虚拟列来指示来源:

      SELECT 'ip' as src, COUNT(...) as cnt
      UNION
      SELECT 'done' as src, COUNT...) as cnt
      

      所以现在您将返回两列,并且可以通过$row['src']$row['cnt'] 访问它们。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-31
        • 1970-01-01
        相关资源
        最近更新 更多