加入多个表导致扩展具有重复属性的单行
Joining multiple tables lead to extend the single row with duplicated attributes
我有 5 个表需要连接在一起:
products:
- product_id
orders
- order_id
order_items
- item_id
- order_id
- product_id
directsells
- directsell_id
directsell_items
- item_id
- directsell_id
- product_id
我正在使用 Zend-Framework,这是我的代码:
$ProductsTable = new Products();
$select = $ProductsTable->select();
$select->from(array('P' => 'products'), array('product_id', 'product_name'));
$select->setIntegrityCheck(false);
$select->joinLeft(array('DI' => 'directsells_items'), 'DI.product_id = P.product_id', array('item_price', 'item_discount', 'qty'));
$select->joinLeft(array('D' => 'directsells'), 'DI.directsell_id = D.directsell_id', array('directsell_number AS invoice_number', 'directsell_date AS invoice_date', 'invoice_status'));
$select->where('DATE(D.directsell_date) BETWEEN "'. date('Y-m-d', strtotime($from_date)) .'" AND "'. date('Y-m-d', strtotime($to_date)) .'"');
$select->where('D.invoice_status <> "Canceled"');
$select->joinLeft(array('OI' => 'order_items'), 'OI.product_id = P.product_id', array('item_price', 'item_discount', 'qty'));
$select->joinLeft(array('O' => 'orders'), 'OI.order_id = O.order_id', array('order_number AS invoice_number', 'order_date AS invoice_date'
,'IF(`order_status` = "10", "Returned", "Active") AS invoice_status'
));
$select->where('DATE(O.order_date) BETWEEN "'. date('Y-m-d', strtotime($from_date)) .'" AND "'. date('Y-m-d', strtotime($to_date)) .'"');
$select->where('O.order_status <> "0"');
$select->where('P.product_id = '. $product_id);
现在我在 directsell_items
中有 2 个条目:
我在 order_items
中有 1 个条目:
我的查询结果是 directsell_items
中的两个条目与 order_item
中的条目合并,如下所示:
我希望一切都清楚。我知道这可能是我加入的问题,但我想不通。
看起来你的直销商品是一种销售商品,你的订单商品是二次销售商品。你只得到两条记录的原因是当你加入时你有效地扩展了一行。不寻找额外的行。
正如@Barmar 所指出的,您需要一个 UNION 来处理这种情况。联合有效地从两个单独的查询中获取记录集,并将它们 returns 作为一个记录集。
因此,您将需要类似(代码未测试)的内容:
$ProductsTable = new Products();
$selectDirect = $ProductsTable->select();
$selectDirect->from(array('P' => 'products'), array('product_id', 'product_name'));
$selectDirect->joinLeft(array('DI' => 'directsells_items'), 'DI.product_id = P.product_id', array('item_price', 'item_discount', 'qty'));
$selectDirect->joinLeft(array('D' => 'directsells'), 'DI.directsell_id = D.directsell_id', array('directsell_number AS invoice_number', 'directsell_date AS invoice_date', 'invoice_status'));
$selectDirect->where('DATE(D.directsell_date) BETWEEN "'. date('Y-m-d', strtotime($from_date)) .'" AND "'. date('Y-m-d', strtotime($to_date)) .'"');
$selectDirect->where('D.invoice_status <> "Canceled"');
$selectDirect->where('P.product_id = '. $product_id);
$selectOrders = $ProductsTable->select();
$selectOrders->from(array('P' => 'products'), array('product_id', 'product_name'));
$selectOrders->joinLeft(array('OI' => 'order_items'), 'OI.product_id = P.product_id', array('item_price', 'item_discount', 'qty'));
$selectOrders->joinLeft(array('O' => 'orders'), 'OI.order_id = O.order_id', array('order_number AS invoice_number', 'order_date AS invoice_date','IF(`order_status` = "10", "Returned", "Active") AS invoice_status'));
$selectOrders->where('DATE(O.order_date) BETWEEN "'. date('Y-m-d', strtotime($from_date)) .'" AND "'. date('Y-m-d', strtotime($to_date)) .'"');
$selectOrders->where('O.order_status <> "0"');
$selectOrders->where('P.product_id = '. $product_id);
$select = $db->select()->union(array($selectDirect, $selectOrders));
我有 5 个表需要连接在一起:
products:
- product_id
orders
- order_id
order_items
- item_id
- order_id
- product_id
directsells
- directsell_id
directsell_items
- item_id
- directsell_id
- product_id
我正在使用 Zend-Framework,这是我的代码:
$ProductsTable = new Products();
$select = $ProductsTable->select();
$select->from(array('P' => 'products'), array('product_id', 'product_name'));
$select->setIntegrityCheck(false);
$select->joinLeft(array('DI' => 'directsells_items'), 'DI.product_id = P.product_id', array('item_price', 'item_discount', 'qty'));
$select->joinLeft(array('D' => 'directsells'), 'DI.directsell_id = D.directsell_id', array('directsell_number AS invoice_number', 'directsell_date AS invoice_date', 'invoice_status'));
$select->where('DATE(D.directsell_date) BETWEEN "'. date('Y-m-d', strtotime($from_date)) .'" AND "'. date('Y-m-d', strtotime($to_date)) .'"');
$select->where('D.invoice_status <> "Canceled"');
$select->joinLeft(array('OI' => 'order_items'), 'OI.product_id = P.product_id', array('item_price', 'item_discount', 'qty'));
$select->joinLeft(array('O' => 'orders'), 'OI.order_id = O.order_id', array('order_number AS invoice_number', 'order_date AS invoice_date'
,'IF(`order_status` = "10", "Returned", "Active") AS invoice_status'
));
$select->where('DATE(O.order_date) BETWEEN "'. date('Y-m-d', strtotime($from_date)) .'" AND "'. date('Y-m-d', strtotime($to_date)) .'"');
$select->where('O.order_status <> "0"');
$select->where('P.product_id = '. $product_id);
现在我在 directsell_items
中有 2 个条目:
我在 order_items
中有 1 个条目:
我的查询结果是 directsell_items
中的两个条目与 order_item
中的条目合并,如下所示:
我希望一切都清楚。我知道这可能是我加入的问题,但我想不通。
看起来你的直销商品是一种销售商品,你的订单商品是二次销售商品。你只得到两条记录的原因是当你加入时你有效地扩展了一行。不寻找额外的行。
正如@Barmar 所指出的,您需要一个 UNION 来处理这种情况。联合有效地从两个单独的查询中获取记录集,并将它们 returns 作为一个记录集。
因此,您将需要类似(代码未测试)的内容:
$ProductsTable = new Products();
$selectDirect = $ProductsTable->select();
$selectDirect->from(array('P' => 'products'), array('product_id', 'product_name'));
$selectDirect->joinLeft(array('DI' => 'directsells_items'), 'DI.product_id = P.product_id', array('item_price', 'item_discount', 'qty'));
$selectDirect->joinLeft(array('D' => 'directsells'), 'DI.directsell_id = D.directsell_id', array('directsell_number AS invoice_number', 'directsell_date AS invoice_date', 'invoice_status'));
$selectDirect->where('DATE(D.directsell_date) BETWEEN "'. date('Y-m-d', strtotime($from_date)) .'" AND "'. date('Y-m-d', strtotime($to_date)) .'"');
$selectDirect->where('D.invoice_status <> "Canceled"');
$selectDirect->where('P.product_id = '. $product_id);
$selectOrders = $ProductsTable->select();
$selectOrders->from(array('P' => 'products'), array('product_id', 'product_name'));
$selectOrders->joinLeft(array('OI' => 'order_items'), 'OI.product_id = P.product_id', array('item_price', 'item_discount', 'qty'));
$selectOrders->joinLeft(array('O' => 'orders'), 'OI.order_id = O.order_id', array('order_number AS invoice_number', 'order_date AS invoice_date','IF(`order_status` = "10", "Returned", "Active") AS invoice_status'));
$selectOrders->where('DATE(O.order_date) BETWEEN "'. date('Y-m-d', strtotime($from_date)) .'" AND "'. date('Y-m-d', strtotime($to_date)) .'"');
$selectOrders->where('O.order_status <> "0"');
$selectOrders->where('P.product_id = '. $product_id);
$select = $db->select()->union(array($selectDirect, $selectOrders));