值不在的值(子查询)

Tim*_*Sum 8 mysql subquery

我一直在努力解决这个问题.我有两张桌子.一个有优惠券和Invoicenumbers.一个有Invoicenumbers和客户名称.

我需要让那些没有使用过特定优惠券的顾客.

以下是表格:

促销表:

Promotions
Invoice | Coupon
----------------
1       | couponA
2       | couponB
3       | couponB
Run Code Online (Sandbox Code Playgroud)

订单表:

Orders
Invoice | Customer
------------------
1       | Jack
2       | Jack
3       | Jill
Run Code Online (Sandbox Code Playgroud)

所以杰克使用了优惠券A和B.而吉尔只使用了优惠券B.

如果我的查询是选择未使用优惠券A的客户,我应该得到吉尔.

这有效,但似乎笨拙和缓慢.有没有更好的办法?

SELECT Customer 
FROM Promotions INNER JOIN Orders
ON Promotions.Invoice = Orders.Invoice
WHERE Customer NOT IN(
    SELECT Customer 
    FROM Promotions INNER JOIN Orders
    ON Promotions.Invoice = Orders.Invoice
    WHERE Coupon = couponA)
GROUP BY Customer
Run Code Online (Sandbox Code Playgroud)

谢谢你的期待!

编辑:这是一个SQLFiddle架构 http://sqlfiddle.com/#!2/21d31/6

Sam*_*ami 5

更新:当它对我们来说很容易做时,我们应该使用偏爱使用连接来获得更好的性能。加入与子查询

Sql小提琴

Select distinct Customer from orders o
join 
(
  SELECT distinct Customer as changedname FROM Orders o2 
  join
  (
     Select distinct invoice from Promotions where Coupon='couponA'
  ) t3
  on o2.invoice = t3.invoice      
) t2
on o.customer != t2.changedname;
Run Code Online (Sandbox Code Playgroud)

注意:我为 t3 更改了列名 customer,因为两个连接的表必须具有不同的列名

解释:

当您拥有大数据时,使用内部或子查询的成本很高。改用连接,让我们学习将子查询转换为连接

使用子查询我们有:

Select distinct Customer from orders where customer not in 
(SELECT distinct Customer FROM Orders where invoice in
(Select distinct invoice from Promotions where Coupon='couponA'));
Run Code Online (Sandbox Code Playgroud)

将子查询转换为join

第一步:

Select distinct Customer from orders o
join 
(
  SELECT distinct Customer as changedname FROM Orders where invoice in
  (Select distinct invoice from Promotions where Coupon='couponA')
) t2
on o.customer != t2.changedname;
Run Code Online (Sandbox Code Playgroud)

第二步:

Select distinct Customer from orders o
join 
(
  SELECT distinct Customer as changedname FROM Orders o2 where invoice 
  join
  (
     Select distinct invoice from Promotions where Coupon='couponA'
  ) t3
  on o2.invoice = t3.invoice      
) t2
on o.customer != t2.changedname;
Run Code Online (Sandbox Code Playgroud)

就是这样,对于具有多行的表要快得多

原答案:

使用not in. 看一看。

Select distinct Customer from orders where customer not in 
(SELECT distinct Customer FROM Orders where invoice in
(Select distinct invoice from Promotions where Coupon='couponA'));
Run Code Online (Sandbox Code Playgroud)

编辑我添加了 distinct 使查询更快

SQL小提琴


das*_*ght 1

请尝试以下查询:

SELECT DISTINCT Customer
FROM Orders o1
WHERE NOT EXISTS (
    SELECT 1 
    FROM Orders o2
    INNER JOIN Promotions ON Promotions.Invoice = o2.Invoice
    WHERE o1.Customer = o2.Customer AND Coupon = 'couponB')
Run Code Online (Sandbox Code Playgroud)

GROUP BY这个想法是通过删除查询顶部的连接来消除,并NOT IN通过创建协调子查询来消除。

这是 sqlfiddle 的链接。