2017-04-17 123 views
0

我有两个表:“合并”完全外部连接而不是?

+-----------------------+ 
| Tables_in_my_database | 
+-----------------------+ 
| orders    | 
| orderTaken   | 
+-----------------------+ 

在订单中,有属性

orderId, orderName, isClosed and orderCreationTime. 

在orderTaken,有属性

userId, orderId and orderStatus. 

比方说,当

orderStatus = 1 --> the customer has taken the order 
orderStatus = 2 --> the order has been shipped 
orderStatus = 3 --> the order is completed 
orderStatus = 4 --> the order is canceled 
orderStatus = 5 --> the order has an exception 

基本上我的项目运行机制是这样的:具有唯一userId的用户将能够从网页接收订单,其中每个订单也具有其自己的唯一orderId。采取后,orderTaken表将记录userId,orderId并初始设置orderStatus = 1.然后,商店根据各种情况更新orderStatus。一旦商店更新了isClosed = 1,那么无论用户采用或不采用该顺序都不会显示(没有意义,但它只是查询中的isClosed == 0)。

现在,我想构建一个网页,将显示用户还没有采取的新订单(应该是orderIds没有记录在该用户的userId下的orderTaken表中的订单),以及用户已经使用orderStatus显示的顺序,但是orderStatus不是4或5,按orderCreationTime DESC组合(如果我没有OrderTakenTime但是让我们保持这种方式,也许没有意义),就像:

OrderId 4 
Order Name: PetPikachu 
orderStatus = 1 
CreationTime: 5am 

OrderId 3 
Order Name: A truck of hamsters 
orderStatus = 3 
CreationTime: 4am 

OrderId 2 
New order 
Order Name: Macbuk bull 
CreationTime: 3am 

OrderId 1 
Order Name: Jay Chou's Album 
orderStatus = 2 
CreationTime: 2am 

我已经基于这样的认识,我得知这个查询写:

SELECT * FROM orders A WHERE A.isClosed == '0' FULL OUTER JOIN orderTaken B WHERE B.userId = '4' AND (B.orderStatus<>'4' OR B.orderStatus<>'5') ORDER BY A.orderCreationTime DESC; 

显然,这查询不工作,但恐怕有

ON A.orderId = B.orderId 

自此之后返回将消除将订单还没有被记录在orderTaken B.我的新订单”表以前也尝试了NOT IN子句像

SELECT * FROM orders A WHERE A.isClosed = '0' AND A.orderId NOT IN (SELECT orderId FROM orderTaken B WHERE B.userId = '$userId' AND (B.orderStatus='4' OR B.orderStatus='5')) ORDER BY creationTime DESC; 

这个查询的作品,但它不会在返回的表有场orderStatus从orderTaken B中。我想在此查询后添加另一个JOIN orderTaken B子句以从B中获取字段,但我认为这不是写好查询的好方法。

我只是想结合“不在”和“全加入”。有人可以帮我吗?谢谢!

回答

0

你似乎想找到未分配给用户(没有在orderTaken一个相关的记录),加上分配给一个用户的那些在orders的记录,但在orderStatus不4或5.

然后不需要完整的外部联接,因为在orders中没有相关记录的orderTaken中将没有记录。甲Left inner join可以用来从orders找到所有的记录,一个on子句将包括来自orderTaken从相关记录数据,然后将where子句可以过滤掉由其他用户执行的命令,或者在orderStatus是4或5:

SELECT o.*, ot.userID, ot.orderStatus 
FROM orders o 
LEFT JOIN orderTaken ot 
ON ot.orderID = o.orderID 
WHERE o.isClosed = 0 
AND (ot.userID IS NULL OR ot.userID = $userID AND ot.orderStatus NOT IN (4,5)) 
ORDER BY o.creationTime DESC 
+0

谢谢泰耶!这正是我想要的!我正在考虑使用LEFT JOIN,但我只是不知道“IS NULL”子句。这是我从你那里学到的关键。再次感谢您解决我的问题! :D – Hang

+0

我现在更正了表名(orderTaken,拼写为orderStatus)。 –

+0

这使得它更加精确。再次感谢Terje! – Hang

1

就像@ terje-d说的,你需要的是LEFT JOIN。用原始表名更新它并修复了$userId过滤器。

  • 对于所有未结订单和未完成订单。
SELECT o.`orderId`, 
      o.`orderName`, 
      ot.`orderStatus`, 
      o.`orderCreationTime` 
    FROM orders o 
LEFT JOIN orderTaken ot 
     ON o.orderId = ot.orderId 
    WHERE o.isClosed = 0 
     AND (
      ot.orderId IS NULL 
     OR ot.orderStatus NOT IN (4,5) 
    ) 
ORDER BY o.`orderCreationTime` DESC 
  • 对于所有未结订单和未完成订单为特定用户
SELECT o.`orderId`, 
      o.`orderName`, 
      ot.`orderStatus`, 
      o.`orderCreationTime` 
    FROM orders o 
LEFT JOIN orderTaken ot 
     ON o.orderId = ot.orderId 
    WHERE o.isClosed = 0 
     AND (ot.orderStatus IS NULL 
     OR (
       ot.user_id = ? 
      AND ot.orderStatus NOT IN (4,5) 
     ) 
    ) 
ORDER BY o.`orderCreationTime` DESC 
+0

是的Jben感谢您的改进答案!是的Terje提供了错误的表名,但逻辑正确,而你的回答只是使它成为完美的110%!并且感谢你选择特定用户的提示!D:你真是太棒了! – Hang

+0

Hi @ j-bin其实我觉得这段代码可能有错误?试图在多个用户同时接受订单的情况下测试此查询se店主帐户创建一个新的新订单,然后运行这个查询我可以看到这个新订单在每个用户的页面上,但是在其中一个用户接受订单后,说userId = 3的那个,然后其他用户喜欢userId = 2或4将不会再次看到此订单,但是此订单将继续显示在userId = 3的页面上,并且状态显示正确。我试图通过采取ot.user_id =来修改代码到where子句并使其如下所示: – Hang

+0

WHERE o.isClosed = 0 AND ot.user_id = 2/4 AND((ot.orderStatus IS NULL)OR(ot.orderStatus NOT IN(4,5))),但是这仍然返回一个空数组。我也尝试把这个user_id的限制放在没有运气的任何其他地方。你还可以看看它,我真的很感激它! :D – Hang