Mysql 如何创建此查询?

Mysql 如何创建此查询?,mysql,sql,join,Mysql,Sql,Join,我有以下表格: actions(id, name) orders(refno, po) order_actions(order, action) 我想获得尚未执行特定操作的所有订单。一个订单可以包含操作,也可以不包含操作 假设我想获得所有尚未应用于动作13的指令,到目前为止,我有如下内容: SELECT o.po, oa.action, FROM orders AS `o` LEFT JOIN order_actions AS `oa` ON o.refno = oa.ord

我有以下表格:

actions(id, name)
orders(refno, po)
order_actions(order, action)
我想获得尚未执行特定操作的所有订单。一个订单可以包含操作,也可以不包含操作

假设我想获得所有尚未应用于动作13的指令,到目前为止,我有如下内容:

SELECT o.po, oa.action, 
    FROM orders AS `o`
    LEFT JOIN order_actions AS `oa` ON o.refno = oa.order
WHERE oa.action <> 13
这对没有操作的订单很有效,但是如果订单的操作不同于13,那么我是否会错过另一个涉及操作表的连接,可能是po的GROUP BY或额外的WHERE子句

感谢您的帮助

SELECT o.po, oa.action
FROM orders AS `o`
     LEFT JOIN order_actions AS `oa` ON o.refno = oa.order
WHERE NOT EXISTS (
  SELECT 1 
  FROM order_actions tmp 
  WHERE oa.order = tmp.order 
    AND tmp.action = '13'
)
sqlfiddle


SQLFIDLE。

您还可以使用GROUPBY和having子句解决此问题:

SELECT o.refno, o.po
FROM orders AS `o` LEFT JOIN
     order_actions `oa`
     ON o.refno = oa.order
group by o.refno, o.po
having max(case when oa.action = 13 then 1 else 0 end) = 0
如果要跟踪此类订单上的所有操作,可以使用group_concat:

SELECT o.refno, o.po,
       group_concat(cast(ao.action) separator ', ') as AllOtherActions
FROM orders AS `o` LEFT JOIN
     order_actions `oa`
     ON o.refno = oa.order
group by o.refno, o.po
having max(case when oa.action = 13 then 1 else 0 end) = 0

您还可以使用GROUPBY和having子句解决此问题:

SELECT o.refno, o.po
FROM orders AS `o` LEFT JOIN
     order_actions `oa`
     ON o.refno = oa.order
group by o.refno, o.po
having max(case when oa.action = 13 then 1 else 0 end) = 0
如果要跟踪此类订单上的所有操作,可以使用group_concat:

SELECT o.refno, o.po,
       group_concat(cast(ao.action) separator ', ') as AllOtherActions
FROM orders AS `o` LEFT JOIN
     order_actions `oa`
     ON o.refno = oa.order
group by o.refno, o.po
having max(case when oa.action = 13 then 1 else 0 end) = 0

另一种选择是:

select o.po
from orders as 'o'
    left join (
        select order from order_actions where [action] = @Action
        ) AS `oa` on o.refno = oa.order
where oa.order is null

这不会为您选择的订单返回操作编号,但您已经声明,您只是在寻找没有操作的订单,我在这里将其称为@action

另一种选择是:

select o.po
from orders as 'o'
    left join (
        select order from order_actions where [action] = @Action
        ) AS `oa` on o.refno = oa.order
where oa.order is null

这不会为您选择的订单返回操作编号,但您已经声明,您只是在寻找没有操作的订单,我在这里将其称为@action

为什么为1,您介意解释一下吗?我尝试了该查询,但它需要很长时间,尚未完成执行。我有大约2.3k的订单和5k的订单操作。您在操作栏上有索引吗?订单是订单操作的主键吗?1只是为了使SELECT不是空的,它可以是X或任何列tmp.order,因为我们对该子选择的结果不感兴趣,只有当它返回或不返回not EXISTS的行时。我创建了索引,实际上ordersid是一个主键,但它永远都需要。不管怎样,谢谢。为什么是1,你能解释一下吗?我尝试了这个查询,但它需要很长时间,它还没有完成执行。我有大约2.3k的订单和5k的订单操作。您在操作栏上有索引吗?订单是订单操作的主键吗?1只是为了使SELECT不是空的,它可以是X或任何列tmp.order,因为我们对该子选择的结果不感兴趣,只有当它返回或不返回not EXISTS的行时。我创建了索引,实际上ordersid是一个主键,但它永远都需要。不管怎样,谢谢。这看起来很复杂。不过这是一个有趣的方法。@JohnBingham。这取决于你如何看待它。对我来说,使用having子句过滤集合的成员似乎一点也不复杂。事实上,它似乎比相关子查询更简单。完全同意,您的查询是我想到的,但不知道如何用SQL表示。这似乎非常复杂。不过这是一个有趣的方法。@JohnBingham。这取决于你如何看待它。对我来说,使用having子句过滤集合的成员似乎一点也不复杂。事实上,它似乎比相关子查询更简单。我完全同意,您的查询是我想的,但不知道如何用SQL表示。