连接和相关子查询

Posted

技术标签:

【中文标题】连接和相关子查询【英文标题】:Joins and correlated subquery 【发布时间】:2017-05-28 10:50:56 【问题描述】:

对于我只想显示未验证订单的客户但不包括已经拥有至少一个已验证订单的客户的情况,无法确定查询。一个客户可以在 DB 中拥有更多记录,因为对于每个订单,客户表中也会创建新记录,因此跟踪特定用户的唯一方法是通过 customer_number。

我的数据库结构(简化):

customers:
id | customer_number

orders:
id | customer_id | isVerified

我可能需要结合连接查询和相关查询(在客户表中搜索每个 customer_number 的记录并检查 isVerified 列是否为假),这最终可能会非常慢,尤其是对于数千条记录。

我使用 Laravel,所以 Eloquent ORM 可以让事情变得更简单。

(第二个想法:或者重写该部分以仅为特定用户的订单创建一个用户记录可能会更快,更有效。)

有什么想法吗?谢谢

【问题讨论】:

【参考方案1】:

可能有几种方法可以做到这一点,但您可以通过连接、聚合和条件求和来实现此结果:

select  a.customer_id,
        sum( case when isVerified = 1 then 1 else 0 end ) as Num_Verified,
        sum( case when isVerified = 0 then 1 else 0 end ) as Num_unVerified
from    customers as a
        left join
        orders as b
        on a.customer_id = b.customer_id
group by a.customer_id
having  Num_Verified = 0
        and Num_unVerified > 0

SQLfiddle here

【讨论】:

我得到了这个满足我的需要的工作:在 a.id = b.customer_id 上并通过 a.customer_number 更改组...谢谢【参考方案2】:

你可以这样实现:

$customer_id = Customer::join('orders','customers.id','orders.cutomer_id')
             ->where('isVerified',true)
             ->select('orders.*')
             ->groupBy('customer_id')
             ->pluck('customer_id');

这将为客户提供至少一份经过验证的订单。

现在获取未验证订单的客户:

$customers = Customer::join('orders','customers.id','orders.customer_id')
             ->where('isVerified',false)
             ->whereNotIn('customer_id',$customer_id)
             ->select('customers.customer_number','orders.*')
             ->groupBy('customer_id')
             ->pluck('customer_id');

【讨论】:

还不知道,等我回来告诉你 好的,祝你好运:D【参考方案3】:

这个怎么样?

$customer_list = customers::where('customer_number',$customer_number)->with('orders',function($query)
$query->where('isVerified',0);
)->get();

【讨论】:

【参考方案4】:

一种方法是聚合查询:

select c.customer_number
from customers c join
     orders o
     on c.customer_id = o.customer_id
group by c.customer_number
having sum(isVerified = 1) = 0 and
       sum(isVerified = 0) > 0;

此结构假定 isVerified 是一个数字,其值为 0 表示假,1 表示真。

【讨论】:

以上是关于连接和相关子查询的主要内容,如果未能解决你的问题,请参考以下文章

连接和相关子查询

MySQL高级第八篇:关联查询子查询和排序相关优化

使用“相关”子查询进行高效连接

17/12/6 子查询

MySQL--5子查询与连接小结

MSSQL之五 连接查询与子查询