Mysql &引用;“合并”;完全外部连接而不是内部连接?

Mysql &引用;“合并”;完全外部连接而不是内部连接?,mysql,join,where,notin,full-outer-join,Mysql,Join,Where,Notin,Full Outer Join,我有两张桌子: +-----------------------+ | Tables_in_my_database | +-----------------------+ | orders | | orderTaken | +-----------------------+ 在顺序中,有属性 orderId, orderName, isClosed and orderCreationTime. userId, orderId and

我有两张桌子:

+-----------------------+
| Tables_in_my_database |
+-----------------------+
| orders                | 
| orderTaken            | 
+-----------------------+
在顺序中,有属性

orderId, orderName, isClosed and orderCreationTime. 
userId, orderId and orderStatus. 
在OrderTake中,有一些属性

orderId, orderName, isClosed and orderCreationTime. 
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的用户将能够从web页面获取订单,其中每个订单也有其唯一的orderId。获取后,OrderTake表将记录用户ID、orderId并初始设置orderStatus=1。然后,商店根据各种情况更新订单状态。一旦商店更新了isClosed=1,那么无论用户是否接受该订单,都不会显示该订单(没有意义,但它只是查询中的isClosed==0)

现在,我想构建一个网页,显示用户尚未接受的新订单(应该是订单ID未记录在该用户的用户ID下的OrderTake表中的订单),以及用户已经接受的订单(显示orderStatus,但orderStatus不是4或5),按orderCreationTime描述分组(是的,如果我没有orderTakenTime,可能没有意义,但让我们保持这种方式),例如:

我根据所学知识编写了此查询:

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;
从那时起,返回的表将删除orderId未记录在OrderTake B中的新订单

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;
此查询可以工作,但在返回的表中没有OrderTake B中的orderStatus字段。我想在这个查询之后添加另一个joinordertake B子句,以从B获取字段,但我认为这不是编写查询的好方法


我只是想把“不加入”和“完全加入”结合起来。有人能帮我吗?谢谢

您似乎希望在
订单
中查找未分配给用户的记录(即,
订单
中没有相关记录)加上分配给用户的记录,但订单状态不是4或5

然后,不需要完全外部联接,因为在
orderstake
中没有记录,而在
orders
中没有相关记录。
左侧内部联接
可用于查找来自
订单
的所有记录,
on
子句将包含来自
ordertake
的相关记录的数据,
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

正如@terje-d所说,您需要的是
左加入
。使用原始表名对其进行了更新,并修复了
$userId
过滤器

  • 适用于所有未结订单和未完成订单
  • 针对特定用户的所有未结订单和未完成订单

谢谢你,泰瑞!这正是我想要的!我想使用LEFT-JOIN,但我不知道“IS-NULL”子句。这是我从你身上学到的关键。再次感谢您解决了我的问题!:DI现在已经更正了表名(OrderTake,拼写错误为orderStatus),这使它更精确。再次感谢泰杰!嗨,Terje D.你能看看我在j-bin的回答下的评论吗?在一个用户接受订单后,您提供的查询还将为其他用户返回一个空集…:(假设userID=3的用户接受订单后,如果我使用userID=4运行您的查询,那么它将返回一个空集。对于多个用户(例如2和3)接受的订单,您希望显示什么,而不是当前用户(4)?您想要一行显示用户4没有接受订单,还是一行显示接受订单的每个用户的相关订单状态?是的,谢谢您改进的答案!是的,Terje给出了错误的表名,但逻辑是正确的,您的答案只是使其达到110%的完美!谢谢您的提示关于如何选择合适的用户!:D你真是太棒了!嗨@j-bin,实际上我认为这段代码可能有漏洞?今天我尝试用多个用户同时接受订单来测试这个查询。我使用店主帐户创建了一个新订单,然后运行这个查询,我可以看到每个用户的页面上都有这个新订单,但是呃,其中一个用户接受了订单,比如说userId=3的用户,那么像userId=2or4这样的其他用户将不会再看到这个订单,但是这个订单会继续显示在userId=3的页面上,并且状态显示正确。我试图修改代码,将ot.user\u id=?带到where子句中,使其类似于:where o.isClosed=0和ot.user_id=2/4和((ot.orderStatus为NULL)或(ot.orderStatus不在(4,5))中),但是这仍然返回一个空数组。我还尝试将此用户id限制放在任何其他地方,但没有成功。您仍然可以看一看吗?我非常感谢!:我猜原因是,一旦有人从这个orderId接受订单,那么这个orderId将记录在ot表中,因此如果我们仍然这样做的话“ON o.orderId=ot.orderId“即使我们将ot.orderId设置为NULL或ot.orderStatus设置为NULL,因为它不再是NULL,所以将不会有结果?如果只有一个用户接受此订单,则此查询的测试将完美进行,但在这一个用户接受订单后,如果我们让userId等于其他用户的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