在 Laravel 中使用子查询

在 Laravel 中使用子查询

子查询

子查询(Sub Query),也称作内查询(Inner Query)或嵌套查询(Nested Query),是一种嵌套在其他 SQL 查询的 WHERE 子句中的查询。

规则

子查询必须遵循以下规则:

  • 子查询必须括在圆括号中
  • 子查询的 SELECT 子句中只能有一个列,除非主查询中有多个列,用于与子查询选中的列相比较
  • 子查询不能使用 ORDER BY,不过主查询可以。在子查询中,GROUP BY 可以起到同 ORDER BY 相同的作用
  • 返回多行数据的子查询只能同多值操作符一起使用,比如 IN 操作符
  • SELECT 列表中不能包含任何对 BLOB、ARRAY、CLOB 或者 NCLOB 类型值的引用
  • 子查询不能直接用在集合函数中 B- ETWEEN 操作符不能同子查询一起使用,但是 BETWEEN 操作符可以用在子查询中

举个例子

来看个示例,示例中子查询用作 SELECT 语句中名为 MaxUnitPrice 的列表达式。示例来自 子查询(SQL Server)

USE AdventureWorks2016;
SELECT Ord.SalesOrderID, Ord.OrderDate,
    (SELECT MAX(OrdDet.UnitPrice)
     FROM Sales.SalesOrderDetail AS OrdDet
     WHERE Ord.SalesOrderID = OrdDet.SalesOrderID) AS MaxUnitPrice
FROM Sales.SalesOrderHeader AS Ord;
GO

Laravel 中的写法

构建 raw 语句

DB::raw 用于在查询中使用原始表达式。不仅限于 raw ,也包括下述其他方法:

  • selectRaw
  • whereRaw / orWhereRaw
  • havingRaw / orHavingRaw
  • orderByRaw

具体用法参考官方文档: Database: Query Builder: Raw Expressions

来看个例子:

$sub = Abc::where(..)->groupBy(..); // Eloquent Builder instance
$count = DB::table( DB::raw("({$sub->toSql()}) as sub") )
->mergeBindings($sub->getQuery()) 
->count();
  • toSql() 获取不带 binding 参数的 SQL 语句
  • getQuery() 获取完整的 SQL 语句
  • mergeBindings() 将 binding 参数合并到查询中

自带闭包

User::whereIn('id', function($query){