我有一个SQL查询从不同的表中提取一些结果,其中一个表 - “订单” - 包含客户详细信息,order_id为PK,另一个表 - order_products - 包含每个订购的产品,参考order_id另一栏为PK。
基本上,我需要知道如何以这样的方式查询数据库:每个order_id只显示一次,order_products表中的数据添加在同一行中,即使客户在该特定行中订购了多个产品订购。
目前,如果订购了多个不同的产品,客户详细信息将在结果中重复 - 我知道为什么会发生这种情况(请参阅查询),但不知道如何以所需格式获得结果输出。我最好的想法是嵌套查询,其中order_products的结果被加载到数组或其他东西,但我甚至不知道这是否可能。
我正在使用MySQL和PHP将结果输出到XML文档中。如果您需要更多信息,请询问!
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
答案 0 :(得分:3)
关系数据库的基本原则之一是列不包含复合数据,这意味着没有数组。它也被称为“first normal form”(1NF)。如果您不希望在产品查询中重复订购信息,则可以运行两个查询而不是一个,一个获取订单,另一个获取产品。
由于无论如何都要处理查询的结果,所以一旦得到结果,您还可以在PHP中处理聚合。您可以先聚合:
$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);
}
}
(假设一个合适的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;
}
}
当然,上述细节并不是生产代码的好设计。 print*
方法(甚至订单打印,通过openOrder
和closeOrder
)可能应该是OrderWriter,CustomerWriter,AddressWriter和ProductWriter类。您可能还想使用XMLWriter而不是回显。
答案 1 :(得分:0)
您可以创建一个用户定义函数,该函数接受订单ID并返回字符串中已订购产品的列表。然后,您只需调用UDF,而不是加入您的uc_order_products表。希望这会有所帮助。
答案 2 :(得分:0)
这是一个过程任务,需要使用PHP或其他语言处理结果集(可能是为您返回数组的db过程)。