SQL вложенный запрос хранится в массиве? - PullRequest
0 голосов
/ 17 ноября 2009

У меня есть SQL-запрос, извлекающий несколько результатов из разных таблиц, одна из таблиц - "orders" - содержит данные о клиенте с 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

Ответы [ 3 ]

3 голосов
/ 17 ноября 2009

Одним из основных принципов реляционных баз данных является то, что столбцы не содержат составных данных, что означает отсутствие массивов. Это также называется " первая нормальная форма " (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);
    }
}

(при условии подходящего класса заказа) или совокупный объем:

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 вместо эхо.

0 голосов
/ 17 ноября 2009

Это процедурная задача, которая потребует обработки результирующего набора с использованием PHP или другого языка (может быть, процедура db, которая возвращает массив для вас).

0 голосов
/ 17 ноября 2009

Вы можете создать пользовательскую функцию, которая будет принимать идентификатор заказа и возвращать список заказанных продуктов в строке. Затем, вместо объединения с вашей таблицей uc_order_products, вы просто вызываете UDF. Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...