【问题标题】:How to sort through large multidimensional array from MySQL Table如何从 MySQL 表中对大型多维数组进行排序
【发布时间】:2012-05-17 07:00:06
【问题描述】:

我有一个 MySQL 表,其中包含客户可以订购的所有可能产品的列表。该表的(非常)简化版本如下所示:

ID  |  productid    |    price    |   age_min   |   age_max   |   type
=======================================================================
1   |   baseball_1  |    12.34    |    18       |    21       |    1
2   |   baseball_2  |    15.99    |    22       |    30       |    1
3   |   baseball_3  |    18.99    |    18       |    99       |    1
4   |   golf_1      |    4.99     |    18       |    24       |    2
5   |   golf_2      |    5.99     |    25       |    44       |    2
6   |   tennis_1    |    9.99     |    18       |    50       |    3
7   |   tennis_2    |    14.99    |    51       |    99       |    3

在这家商店,所有产品都有年龄限制,这意味着客户只有在他/她的年龄符合该范围的情况下才能选择要购买的商品。即使每个产品“类型”存在多个选项,定制也只能选择一种“类型”。在上面的示例表中,24 岁的客户只能选择:

棒球_2、棒球_3 高尔夫_1 和网球_1

我正在尝试按已知产品类型组织潜在客户的选项。因此,就我而言,商店可能会向客户展示:

棒球选项

  • baseball_2 - 15.99 美元
  • baseball_3 - 18.99 美元

高尔夫选项

  • golf_1 - 4.99 美元

网球选项

  • tennis_1 - 9.99 美元

我想使用 age 变量对数据库进行一次(如果可能的话)MySQL 调用,并返回所有可能的产品,然后如上所述相应地显示这些产品。 SQL 语句很简单,我已经完成了这项工作,但我不确定如何循环或构建一个可以列出成员可用选项的适当数组。

可能会建议,但这比显示的要详细得多,并且由于与该问题无关的其他几个因素,因此不能选择使用任何类型的第三方软件或购物车。看来这是如何处理多维数组的问题。有没有人遇到过类似的问题?


更新

虽然 Travesty 和 tdammer 下面提供的解决方案在某些情况下是有效的,但我希望能够对我的数据做更多的事情,然后将其从我的数据库中显示出来。页面的布局和设计不应取决于它在数据库中的存储方式/时间/等。有时我想先显示一组“类型”的最高价格,而先显示另一组“类型”的最低价格。

通过使用 fetchAll 语句,我能够从查询中收集我需要的所有必要数据,但我真的不确定如何使用它。比如我的数组目前是:

Array (
    [0] => Array ( [productid] => 394, [price] => 6.20,  [type] => 16 ),
    [1] => Array ( [productid] => 395, [price] => 12.40, [type] => 16 ),
    [2] => Array ( [productid] => 396, [price] => 18.60, [type] => 16 ),
    [3] => Array ( [productid] => 397, [price] => 24.80, [type] => 16 ),
    [4] => Array ( [productid] => 398, [price] => 31.00, [type] => 16 ),
    [5] => Array ( [productid] => 449, [price] => 4.20,  [type] => 17 ),
    [6] => Array ( [productid] => 450, [price] => 8.40,  [type] => 17 ),
    [7] => Array ( [productid] => 451, [price] => 12.60, [type] => 17 ),
    [8] => Array ( [productid] => 452, [price] => 16.80, [type] => 17 ),
    [9] => Array ( [productid] => 453, [price] => 21.00, [type] => 17 )
)

有没有一种好方法来构建我自己的数组,我以后基本上可以说“向我显示所有类型为 17 的商品的 productid 和 price”?

【问题讨论】:

  • 您确定多维数组真的是您想要的吗?我已经多次看到类似的问题,今天早上刚刚回答了另一个:stackoverflow.com/q/10501112/259457。这就是你遇到的问题吗?
  • @Travesty3 - 我不是来自两个表作为你的原始海报并且仍然有些不同,尽管我相信你更改标题的方式非常有趣,也许是我想要达到的。我会玩一会儿。

标签: php mysql arrays multidimensional-array pdo


【解决方案1】:

根据您的数据库大小,此解决方案可能不起作用,但通常我在较小规模上的工作方式是:

将数据库结果循环到我设计的数组中

所以我可能有

Array['baseball'][0]['price'] = 15.99
Array['baseball'][1]['price'] = 18.99

循环遍历我创建的数组以解析结果。

在更大的数据库中,您将需要不同的解决方案,因为这会使您多次循环结果结果...

【讨论】:

    【解决方案2】:

    你不需要多维数组。

    只需按类型对查询结果进行排序,然后在数组中循环。这样做时,在第一个项目之前插入一个标题,然后在类型发生变化的每个项目之前插入一个标题。

    如果您有一个正确规范化的数据库,您还应该有一个 product_types 表来保存您的产品类型 ID 和名称;在这种情况下,考虑JOIN。你的 SQL 看起来有点像这样:

    SELECT p.id, p.name, p.price, t.id AS type_id, t.name AS type_name FROM products AS p LEFT JOIN product_types t ON t.id = p.type WHERE :age BETWEEN p.min_age AND p.max_age;
    

    然后,您将逐步检查结果集,如下所示:

    $current_type = 'not_a_string';
    while ($row = get_next_row_from_database) {
        if ($current_type !== $row['type_id']) {
            echo '<h3>' . htmlspecialchars($row['type_name']) . '</h3>';
            $current_type = $row['type_id'];
        }
        printf('<p>%s - $%2.2f</p>', htmlspecialchars($row['name']), $row['price']);
    }
    

    这种方法使用常量内存(在网络服务器上,显然不在数据库上)和线性时间。

    您还应该考虑对数据进行分页:不要一次查询所有行,而是运行 COUNT(*) 查询以获取总行数,然后使用 LIMIT 仅获取当前页面(您可能还想指定 ORDER BY 子句以使您的页面有意义)。

    【讨论】:

    • 虽然我的问题可能使我相信我只需要输出一次数据,但我确实有很多用途,而且您和 travesty 都提到的方法几乎没有灵活性,因为它只是排序通过行。我已经测试了几个小时,但它确实没有按需要工作。我在想一个多维数组实际上是我需要使用它的方式。 (你的方法只允许我输出,而不是根据需要在页面上放置特定的类型、价格等)。Job Brown 在下面描述的方法最终是现在需要的。
    【解决方案3】:

    我认为您不需要多维数组。我认为当你来到一个新组时,你只需要遍历你的行并更改你的标题。

    我对这个答案使用了一点不同的方法,将每一行粘贴到一个数组中,然后将它们内爆,以便保留格式。

    //USING PDO - assume connection already made
    /* added ORDER BY in the query to ensure that we get the rows sequentially, by type */
    $stmt = $db->prepare("SELECT * FROM table WHERE age_min >= :age AND age_max <= :age ORDER BY type");
    $stmt->bindParam(":age", $customer_age);
    $stmt->execute();
    
    $type = -1;
    $lines = array();
    while ($data = $stmt->fetch(PDO::FETCH_ASSOC))
    {
        $data = array_map("htmlspecialchars", $data); /* sanitize data for HTML output */
    
        if ($type != $data["type"])
        {
            $type = $data["type"];
            list($typeName) = explode("_", $data["productid"]); /* this assumes that you don't have a column with the actual product name. If you do, use that instead. */
            $lines[] = (count($lines) > 0 ? "</ul>\n" : "") ."<h2>". ucfirst($typeName) ." Option</h2>\n<ul>";
        }
    
        $lines[] = "\t<li>{$data["productid"]} - {$data["price"]}</li>";
    }
    
    echo implode("\n", $lines) ."\n</ul>";
    


    对问题更新的回应:

    有没有一种好方法来构建我自己的数组,我以后基本上可以说“向我显示所有类型为 17 的商品的 productid 和 price”?

    这是一个查询。我仍然认为没有理由将其存储在数组中。如果您想获取类型为 17 的所有商品的 productid 和 price,那么您应该在数据库上执行该查询。如果您想对结果进行不同的排序,则应更改 ORDER BY 子句。

    也许你需要调整你的查询,让它更灵活一点:

    if (!isset($_POST["columns"]))
        $_POST["columns"] = "productid, price";
    if (!isset($_POST["whereClause"]))
        $_POST["whereClause"] = "TRUE";
    if (!isset($_POST["orderby"]))
        $_POST["orderby"] = "type ASC, price DESC";
    
    $stmt = $db->prepare("SELECT :columns FROM table WHERE age_min >= :age AND age_max <= :age AND :whereClause ORDER BY :orderby");
    $stmt->bindParam(":columns", $_POST["columns"]);
    $stmt->bindParam(":age", $customer_age);
    $stmt->bindParam(":whereClause", $_POST["whereClause"]);
    $stmt->bindParam(":orderby", $_POST["orderby"]);
    $stmt->execute();
    

    您可以通过 HTML 表单提交(导致页面重新加载)调用它,也可以通过 AJAX 调用它。但无论哪种方式,我都看不出执行fetchAll 并将结果存储在数组中对您有什么好处。

    【讨论】:

    • 对于具有良好格式(制表符、换行符等)的 HTML 输出,我有点强迫症,这就是字符串中 \n\t 的原因。当您运行 PHP 脚本并查看源代码以查看生成的实际 HTML 时,更容易找出问题所在。
    • 你应该对正确地转义你的 HTML 输出有强迫症。 PHP 肯定不会让你的生活变得轻松,但如果你不恰当地使用 htmlspecialchars() 和朋友,你应该成为 XSS'd。
    • 我正在考虑更多,尽管我会继续回答这个问题 - 它极大地限制了我转置数据的能力。在这一点上,一切都是关于我如何将事物存储在数据库中。例如,如果我知道一个客户标题将包含多个项目(比如棒球和高尔夫要一起列出),那么这个选项并不能真正帮助我。我得把它弄乱一些。
    • @tdammers:是的,使用htmlspecialchars() 进行清理肯定不会有什么坏处,但我假设数据库中的数据由管理员维护,而不是来自用户输入。
    • @JM4:我忘记发布我对查询所做的编辑。您还应该将ORDER BY type 添加到查询中,以便按该顺序获取行。这样,您可以确保所有具有相同类型的行都位于相同的标题下。查看更新的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-03
    • 2021-07-02
    • 2017-08-27
    • 1970-01-01
    • 2010-10-13
    相关资源
    最近更新 更多