MySQL连接查询以创建自定义报告

时间:2013-06-23 04:57:39

标签: mysql join left-join outer-join

假设我在MySQL数据库中有两个表。第一个名为products,第二个名为sales

让我为products表格保留三个不同的条目......

+-------+-----------------+-----------+--------+
|id     | productname     | quantity  | uom    |
+-------+-----------------+-----------+--------+
|1      | water bottle    | 20        | piece  |
|2      | cable           | 200       | meter  |
|3      | soap            | 1         | piece  |
+-------+-----------------+-----------+--------+

此外,我在sales表格中输入的内容很少 -

+-------+---------------------+-----------+--------+-----------+
|id     | date                | quantity  | uom    | productid |
+-------+---------------------+-----------+--------+-----------+
|1      | 2013-06-21 09:34:00 | 20        | meter  |     2     |
|2      | 2013-06-21 10:35:00 | 100       | meter  |     2     |
|3      | 2013-06-21 11:36:00 | 1         | piece  |     3     |
+-------+---------------------+-----------+--------+-----------+

上面的salesproductidforeign key。每个销售条目都保留productid。现在,如何使用左表中的单个条目和基于外键的右表中的多个条目创建报告。

让我创建一个报告的模型 -

+-----------------+-----------+--------+---------------------+-----------+
| productname     | quantity  | uom    | date                | quantity  |
+-----------------+-----------+--------+---------------------+-----------+
| cable           | 200       | meter  | 2013-06-21 09:34:00 | 20        |
|                 |           |        | 2013-06-21 10:35:00 | 100       |
| soap            | 1         | piece  | 2013-06-21 11:36:00 | 1         |
| water bottle    | 20        | piece  |                     |           |
+-----------------+-----------+--------+---------------------+-----------+

是否可以使用MySQL创建基于外键的上述报告?

2 个答案:

答案 0 :(得分:1)

更新 从结果集中呈现报表的客户端代码不是为RDBMS做的工作。

使用JOIN生成结果集,然后根据您的选择使用客户端脚本语言构建报表的布局。

如果是php,您可能会发现在查询中使用GROUP_CONCAT()并在php端使用explode()非常方便。

SELECT p.productname, 
       p.quantity total_quantity, 
       p.uom, 
       GROUP_CONCAT(CONCAT(COALESCE(s.date, ''),'|',COALESCE(s.quantity, '')) ORDER BY s.date) details
  FROM products p LEFT JOIN sales s 
    ON p.id = s.productid
 GROUP BY s.productid, p.productname, p.quantity, p.uom
 ORDER BY p.productname

示例输出:

|  PRODUCTNAME | TOTAL_QUANTITY |   UOM |                                        DETAILS |
------------------------------------------------------------------------------------------
|        cable |            200 | meter | 2013-06-21 09:34:00|20,2013-06-21 10:35:00|100 |
|         soap |              1 | piece |                          2013-06-21 11:36:00|1 |
| water bottle |             20 | piece |                                              | |

这是 SQLFiddle 演示。

使用PDO的php代码可能看起来像

<?php
$db = new PDO('mysql:host=localhost;dbname=database_name', 'user', 'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);


$sql = "SELECT p.productname, 
               p.quantity total_quantity, 
               p.uom, 
               GROUP_CONCAT(CONCAT(COALESCE(s.date, ''),'|',COALESCE(s.quantity, '')) ORDER BY s.date) details
          FROM products p LEFT JOIN sales s 
            ON p.id = s.productid
         GROUP BY s.productid, p.productname, p.quantity, p.uom
         ORDER BY p.productname";

$query = $db->prepare($sql);
$query->execute();
$rows = $query->fetchall(PDO::FETCH_ASSOC);

$query = null;
$db = null;
?>

<table>
    <thead>
        <tr>
            <th>Product Name</th>
            <th>Total quantity</th>
            <th>UOM</th>
            <th>Date</th>
            <th>Quantity</th>
        </tr>
    </thead>
    <tbody>
<?php
    foreach($rows as $row) {
        echo "<tr>
              <td>{$row['productname']}</td>
              <td>{$row['total_quantity']}</td>
              <td>{$row['uom']}</td>";
        $details = explode(',', $row['details']);
        $i = 1;
        foreach($details as $detail) {
            list($date, $quantity) = explode('|', $detail);
            if ($i > 1) {
                echo "<td></td><td></td><td></td>";
            }
            echo "<td>$date</td>
                  <td>$quantity</td></tr>";
            $i++;    
        }
    }
?>        
    </tbody>
</table>

哪会产生结果

Product Name  Total quantity  UOM    Date                 Quantity
cable                    120  meter  2013-06-21 09:34:00        20
                                     2013-06-21 10:35:00       100
soap                       1  piece  2013-06-21 11:36:00         1
water bottle              20  piece                               

答案 1 :(得分:0)

您可以在查询结束时使用join和group by查询,但据我所知,MySQL查询的回复不会返回行中的空字段。

    select products.productname , sales.quantity , sales.uom , sales.date , sales.quantity from sales, products where sales.product.id =  products.product.id group by products.productname , sales.date

如您所见,查询的答案将具有重复的productname,但在其他列中具有不同的值。