连接多个表会导致使用重复属性扩展单行

时间:2017-11-01 15:31:01

标签: mysql join zend-framework2 left-join

我需要连接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 entries in directsell_items table

我在order_items中有一个单独的条目: 1 entries in order_items table

我的查询结果是directsell_items中的两个条目与order_item中的条目合并,如下所示:

Result of my query

我希望一切都清楚。我知道这可能是我加入的一个问题,但我无法理解。

1 个答案:

答案 0 :(得分:2)

看起来您的直销商品是一种商品销售,而您的订单商品是第二次商品销售。您只获得两条记录的原因是,当您加入“有效扩展行”时。不寻找额外的行。

正如@Barmar所说,你需要一个UNION来处理这种情况。 union有效地从两个单独的查询中获取记录集,并将它们作为一个记录集返回。

所以,你需要的东西(代码未测试):

$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));