简体   繁体   English

SQL嵌套查询存储在数组中吗?

[英]SQL nested query in stored in an array?

I have an sql query pulling a few results from different tables, one of the tables - "orders" - contains customer details with an order_id as a PK, another table - order_products - contains each product ordered, with reference to the order_id and another column as PK. 我有一个sql查询,从不同的表中提取一些结果,其中一个表-“ orders”-包含以order_id作为PK的客户详细信息,另一个表-order_products-包含所订购的每个产品,并引用了order_id和另一列作为PK。

Basically, I need to know how to query the database in such a way that each order_id is only displayed once, with data from the order_products table added within the same row, even if customers have ordered more than one product in that particular order. 基本上,我需要知道如何查询数据库,使得每个order_id仅显示一次,并且将order_products表中的数据添加到同一行中,即使客户已按该特定顺序订购了多个产品。

Currently customer details are being repeated within the results if they have ordered multiple different products - I know why this is happening (see query) but don't know how to get the results output in the required format. 当前,如果客户订购了多种不同的产品,则会在结果中重复显示客户详细信息-我知道为什么会这样(请参阅查询),但不知道如何以所需的格式输出结果。 My best idea would be a nested query, in which the results from the order_products are loaded into an array or something but I don't even know if that would be possible. 我最好的主意是嵌套查询,其中将order_products的结果加载到数组等中,但是我什至不知道这样做是否可行。

I am using MySQL and PHP with the results to then be output in an XML document. 我正在使用MySQL和PHP,并将结果输出到XML文档中。 If you need any more info please ask! 如果您需要更多信息,请询问!

SELECT uc_orders.order_id, uc_orders.order_total, uc_orders.primary_email, 
    uc_orders.delivery_first_name, uc_orders.delivery_last_name, 
    uc_orders.delivery_street1, uc_orders.delivery_street2, uc_orders.delivery_city, 
    uc_orders.delivery_zone, uc_orders.delivery_postal_code, uc_zones.zone_name, 
    uc_order_products.title, uc_order_products.price 
  FROM uc_orders 
    LEFT JOIN uc_zones ON uc_orders.delivery_zone = uc_zones.zone_id 
    LEFT JOIN uc_order_products ON uc_orders.order_id = uc_order_products.order_id 
  ORDER BY order_id

One of the basic tenets of relational databases is that columns don't hold compound data, which means no arrays. 关系数据库的基本原则之一是列不包含复合数据,这意味着没有数组。 It's also called " first normal form " (1NF). 也称为“ 第一范式 ”(1NF)。 If you don't want repeated order info within the product query, you can run two queries rather than one, one that gets the orders and the second that gets the products. 如果您不希望在产品查询中重复获取订单信息,则可以运行两个查询,而不是一个查询,一个查询获取订单,第二个查询获取产品。

Since the result of the query is being processed anyway, you can also take care of aggregation within PHP once you get the result. 由于查询结果仍在处理中,因此,获得结果后,您还可以在PHP中进行聚合。 You can aggregate first: 您可以先汇总:

$orders=array();
while ($row = $result->fetch()) {
    if (! isset($orders[$row['order_id']])) {
        $orders[$row['order_id']] = new Order($row);
    } else {
        $orders[$row['order_id']]->addProducts($row);
    }
}

(assuming a suitable Order class), or aggregate in-line: (假设合适的Order类),或在线汇总:

class OrderList {
    ...
    function printXML($result) {
       $currOrderID = null;
       echo '<orders>'
       while ($row = $result->fetch()) {
           if ($currOrderID != $row['order_id']) {
               $this->closeOrder();
               $this->openOrder($row);
           }
           $this->printProduct($row);
       }
       $this->closeOrder();
       echo '</orders>';
    }

    function openOrder($row) {
        echo "<order id='$row[order_id]'><total>$row[order_total]</total>";
        $this->printCustomer($row);
        echo '<products>';
    }

    function printProduct($row) {
        echo "<product><title>$row[title]</title><price>$row[price]</price></product>\n";
    }

    function closeOrder() {
        echo '</products></order>';
    }

    function printCustomer($row) {
        echo <<EOS;
          <customer>
            <email>$row[primary_email]</email>
            <first_name>$row[delivery_first_name]</first_name>
            ...
EOS;
        $this->printAddress($row);
        echo '</customer>';
    }

    function printAddress($row) {
        echo <<EOS;
          <address>
            <street line="1">$row[delivery_street1]</street>
            <street line="2">$row[delivery_street2]</street>
            ...
          </address>
EOS;
    }
}

Of course, the specifics of the above is not a good design for production code. 当然,上面的细节对于生产代码来说并不是一个好的设计。 The print* methods (and even order printing, via the openOrder and closeOrder ) probably deserve to be OrderWriter, CustomerWriter, AddressWriter and ProductWriter classes. print*方法(甚至通过openOrdercloseOrder订单打印)可能应该是OrderWriter,CustomerWriter,AddressWriter和ProductWriter类。 You might also want to use XMLWriter rather than echoing. 您可能还想使用XMLWriter而不是回显。

You could create a User Defined Function that would accept order id and return a list of ordered products in a string. 您可以创建一个用户定义函数,该函数将接受订单ID并以字符串形式返回已订购产品的列表。 Then, instead of joining with your uc_order_products table, you simply call the UDF. 然后,您无需调用uc_order_products表,而只需调用UDF。 Hope this helps. 希望这可以帮助。

这是一个过程性任务,需要使用PHP或其他某种语言(可能是为您返回数组的db过程)处理结果集。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM