使用PDO从MySQL打印矩阵表

时间:2015-08-19 12:22:16

标签: php mysql matrix pdo

我有三个表countriesproduct_categoriesvats,包括以下信息

product_categories
包括两列product_category_codeproduct_category_name_en

国家
table: countries

大桶
table: vats

和一个包含以下查询的视图vats_view

SELECT 
    countries.country_code,
    product_categories.product_category_code,
    product_categories.product_category_name_en,
    vats.vat,
    vats.editedBy,
    vats.editedTimestamp
FROM
    vats,
    countries,
    product_categories
WHERE
    countries.country_code = vats.country
    AND product_categories.product_category_code = vats.product_category 

我想根据这些信息创建一个HTML矩阵表。在这种情况下,表格看起来像

---------------------------------------------------
|             |   AL   |   DE   |   DK   |   SE   |
---------------------------------------------------
| Category 10 | 14.00  |        |        | 10.00  |
| Category 20 | 15.00  |        |        |        |
| Category 30 |        |        |        |        |
---------------------------------------------------

我已经完成了以下代码。我知道这是完全错误的,还没有工作,但是我想知道如何做到这一点。

echo "<table class=\"table table-bordered\"><tr><th></th>";
    $sql = $pdo->query("SELECT country_code FROM countries WHERE active = 1 ORDER BY country_code ASC");

    while($country = $sql->fetch(PDO::FETCH_ASSOC)) {
        echo "<th class=\"text-center\">".$country['country_code']."</th>";
    }
    echo "</tr>";
    $sql = $pdo->query("SELECT * FROM product_categories");

    while($vat = $sql->fetch(PDO::FETCH_ASSOC)) {
        echo "<tr><td>".$vat['product_category_name_'.$lang]."</td>";
        $sqlvats= $pdo->query("SELECT * FROM vats_view WHERE product_category_code = '".$vat['product_category_code']."'");

        while($row = $sqlvats->fetch(PDO::FETCH_ASSOC)) {
            echo "<td>".$row['vat']."</td>";
        }
        echo "</tr>";
     }
     echo "</table>";

欢迎任何想法。提前谢谢。

2 个答案:

答案 0 :(得分:0)

好的,所以我修复了第二个查询以使用正确的$ vat变量,用准备好的语句替换了第三个查询(只是一个很好的做法)并将if替换为if来处理空结果

echo "<table class=\"table table-bordered\"><tr><th></th>";
$sql = $pdo->query("SELECT country_code FROM countries WHERE active = 1 ORDER BY country_code ASC");

while($country = $sql->fetch(PDO::FETCH_ASSOC)) {
    echo "<th class=\"text-center\">".$country['country_code']."</th>";
}
echo "</tr>";
$vat = $pdo->query("SELECT * FROM product_categories");

while($vat = $sql->fetch(PDO::FETCH_ASSOC)) {
    echo "<tr><td>".$vat['product_category_name_'.$lang]."</td>";
    $sqlvats = $pdo->prepare("SELECT * FROM vats_view WHERE product_category_code = ?");
    $sqlvats->bindParam(1, $vat['product_category_code']);
    $sqlvats->execute();

    if ($row = $sqlvats->fetch(PDO::FETCH_ASSOC)) {
        echo "<td>".$row['vat']."</td>";
    } else {
        echo "<td></td>";
    }
    echo "</tr>";
 }
 echo "</table>";

答案 1 :(得分:0)

最直接的方法可能是

SELECT
  *
FROM 
  (SELECT
    countries.country_code,
    V1.vat,
    V1.product_category_name_en product
  FROM 
    (SELECT 
      product_categories.product_category_name_en,
      vats.vat,
      vats.country
    FROM vats
    RIGHT OUTER JOIN product_categories
      ON vats.product_category = product_categories.product_category_code
    ) V1
  LEFT OUTER JOIN countries
    ON countries.country_code = V1.country
  )
PIVOT
  (MAX(vat) FOR country_code IN ('AL' AL, 'DE' DE, 'DK' DK, 'SE' SE))
ORDER BY product
;

但遗憾的是,这不兼容MySQL - 适用于Oracle:SQL Fiddle

然而,遵循这条道路:

CREATE OR REPLACE VIEW V1 AS
  SELECT 
    product_categories.product_category_name_en,
    vats.vat,
    vats.country
  FROM vats
  RIGHT OUTER JOIN product_categories
    ON vats.product_category = product_categories.product_category_code
;

CREATE OR REPLACE VIEW V2 AS
  SELECT
    V1.product_category_name_en product,
    countries.country_code,
    V1.vat
  FROM V1
  LEFT OUTER JOIN countries
    ON countries.country_code = V1.country
;

...并使用PIVOT'替代':

SELECT
  product,
  MAX(CASE WHEN country_code = 'AL' THEN vat END) AL,
  MAX(CASE WHEN country_code = 'DE' THEN vat END) DE,
  MAX(CASE WHEN country_code = 'DK' THEN vat END) DK,
  MAX(CASE WHEN country_code = 'SE' THEN vat END) SE
FROM V2
GROUP BY product
ORDER BY product
;

......我们可以得到

的要求
|     product |     AL |     DE |     DK |     SE |
|-------------|--------|--------|--------|--------|
| Category 10 |     14 | (null) | (null) |     10 |
| Category 20 |     15 | (null) | (null) | (null) |
| Category 30 | (null) | (null) | (null) | (null) |

查看实际操作:SQL Fiddle

您可能希望将最后一个SELECT封装在另一个视图中,以便将数据处理留给数据库,并使代码保持整洁......

如果需要调整/进一步详细说明,请发表评论。