原始 SQL 到 laravel 查询

Posted

技术标签:

【中文标题】原始 SQL 到 laravel 查询【英文标题】:raw SQL to laravel query 【发布时间】:2018-04-28 16:55:50 【问题描述】:

谁能帮我写一个数据库查询版本的下面的 SQL 语句。 我需要一些关于 select 语句和分区连接的帮助。

到目前为止,我已经做到了。

$query = DB::table(raw('SapakInAdminOrder a'))
->select(raw('a.*'))
->leftJoin(raw('currency cu'), 'a.currency', '=', 'cu.id')
->leftJoin(raw('moodboards m'), 'a.orderMoodboardID', '=', 'm.id')
 ->join(raw('clients b'), 'a.clientID', '=', 'b.id')
 ->leftJoin(raw('moodboards mc'), 'b.moodboardID', 'mc.id')
 ->join(raw('sapakim c'), 'b.sapakID', '=', 'c.id')
 ->leftJoin(raw('sapakim sm'), 'c.managerid', '=', 'sm.id')
 ->leftJoin(raw('products p'), 'a.productKey', '=', 'p.id')
 ->where(function ($query) 
     $query->whereNull('a.isDeleted');
     $query->orWhere('a.isDeleted', '!=', 1);
 );

但我需要做到这一点。

select * from (select ROW_NUMBER() OVER(ORDER BY case when (indesign.status=4 or indesign.statusdate is null) then getdate()+2 else indesign.statusdate end ASC) AS RowNum,a.*
FROM sapakInAdminOrder a 
left join currency cu on cu.id=a.currency
left join moodboards m on m.id=a.orderMoodboardID 
inner join Clients b on a.clientID=b.id 
left join moodboards mc on mc.id=b.moodboardID 
inner join Sapakim c on b.sapakID=c.id 
left join Sapakim sm on sm.id=c.managerid  
left join products p on p.id=a.productKey 
left join (select * from (select ROW_NUMBER() over(PARTITION BY orderID ORDER BY id DESC) r, * from orderCommunication ) f where r=1) chat on chat.orderId = a.id
left join (select id,[status],orderid,approveSMSDate,coverImage,statusDate from (SELECT  id,[status],statusDate,approveSMSDate,coverImage,orderid,ROW_NUMBER() OVER(PARTITION BY orderid ORDER BY id DESC) AS r  FROM  SapakimInAdminDesigns) f where  r=1) indesign on a.id=indesign.orderid
where (a.isDeleted is null or a.isDeleted != 1) and 
      c.inAdminManagerID=(select id from sapakim where sapakguid='test')  and 
      c.sapakguid='test' and 
      a.isFreeDesign=0 and 
      a.transactionID = -1 and 
      (a.designerPaid is null or a.designerPaid=0) and 
      (chat.sentToPrinter is null and chat.sentToManager is null and chat.sentToDesigner is null)
) bb where RowNum>=1 and RowNum<31 
ORDER BY  RowNum asc

我可以做一些简单的事情,但不能完全理解分区连接和 select 语句

非常感谢您对此的帮助。

提前致谢。

【问题讨论】:

分享一些 SQL 以设置测试架构并在预期结果旁边播种一些数据会很有帮助 【参考方案1】:

我也遇到了这种类型的问题,但我找到了解决方案,而且对我来说效果很好!

对这种类型的查询使用 DB::unprepared()

$path = base_path() . "/storage/agency.sql";
$sql = file_get_contents($path);
DB::unprepared(DB::raw($sql));

Laravel 中的所有 SQL 命令默认都是准备好的,但有时你需要在未准备模式下执行命令,因为某些数据库中的某些命令无法在准备模式下运行。

【讨论】:

我可以简单地使用 DB::query() 查询它,但这不是一个优雅的解决方案。 DB::unprepared 运行原始查询,不需要 DB::raw。如果文件被泄露,从文本文件(尤其是存储文件夹中的文件)加载查询是自找麻烦。最好使用存储库模式并在源代码中使用 DB::select()。【参考方案2】:

这是你的意思吗?

$result = DB::Select("select * from (select ROW_NUMBER() OVER(ORDER BY case when (indesign.status=4 or indesign.statusdate is null) then getdate()+2 else indesign.statusdate end ASC) AS RowNum,a.*
FROM sapakInAdminOrder a 
left join currency cu on cu.id=a.currency
left join moodboards m on m.id=a.orderMoodboardID 
inner join Clients b on a.clientID=b.id 
left join moodboards mc on mc.id=b.moodboardID 
inner join Sapakim c on b.sapakID=c.id 
left join Sapakim sm on sm.id=c.managerid  
left join products p on p.id=a.productKey 
left join (select * from (select ROW_NUMBER() over(PARTITION BY orderID ORDER BY id DESC) r, * from orderCommunication ) f where r=1) chat on chat.orderId = a.id
left join (select id,[status],orderid,approveSMSDate,coverImage,statusDate from (SELECT  id,[status],statusDate,approveSMSDate,coverImage,orderid,ROW_NUMBER() OVER(PARTITION BY orderid ORDER BY id DESC) AS r  FROM  SapakimInAdminDesigns) f where  r=1) indesign on a.id=indesign.orderid
where (a.isDeleted is null or a.isDeleted != 1) and 
      c.inAdminManagerID=(select id from sapakim where sapakguid='test')  and 
      c.sapakguid='test' and 
      a.isFreeDesign=0 and 
      a.transactionID = -1 and 
      (a.designerPaid is null or a.designerPaid=0) and 
      (chat.sentToPrinter is null and chat.sentToManager is null and chat.sentToDesigner is null)
) bb where RowNum>=1 and RowNum<31 
ORDER BY  RowNum asc"); 

【讨论】:

应该是 DB::query() 但这不是我的意思【参考方案3】:

也许您应该为这些分区查询创建一个数据库视图? 然后您可以在之后加入数据库中的视图。

从技术上讲,这些分析功能通常不受框架支持。

【讨论】:

这意味着我们无法在 laravel 中做到这一点? 并非所有的 DB 都支持分析功能。 ORM-s 是通用的并支持所有可能的数据库引擎。在 ORM 中实现这些复杂的查询是没有意义的,大多数人甚至不知道它们的存在。有一些例外,例如 JOOQ,但这不是 php 语言 (blog.jooq.org/2013/11/03/…)。【参考方案4】:

看看这个名为 Orator 的新 Laravel 工具。它可以让你简单地粘贴“遗留”SQL 并返回 Laravel 的 DB Query Builder 语法。

Laravel Orator News Article

Online Conversion Tool

【讨论】:

【参考方案5】:

假设你想在前端显示这个,使用 eloquent 模型的关系, https://laravel.com/docs/master/eloquent-relationships#one-to-one

在模型 User 中,有一个由方法 phone() 识别的一对一关系,如果您转到我假设传递 $user 变量的显示视图,请执行以下操作

<?php dd($user->phone); ?>

如果你不是这个意思,我可能会错过问题的全部意义。

【讨论】:

【参考方案6】:

您可以为此目的使用以下软件包。

特点

    将 SQL 查询转换为 Laravel 查询生成器。 按照 Laravel 文档中的说明协助构建查询。 提供与之交互的选项,以生成不同的结果。

SQL to Laravel Query Builder, A Converter written in PHP

【讨论】:

以上是关于原始 SQL 到 laravel 查询的主要内容,如果未能解决你的问题,请参考以下文章

将原始 SQL 查询传递给 Laravel 上的查询构建器

如何使用 Laravel 的流畅查询构建器混合原始 SQL 和非原始 SQL

在 Laravel 4 中转义原始 SQL 查询

在 Laravel 5 Eloquent 中获取原始 SQL 查询的结果

将原始 SQL 转换为 Laravel 查询构建器

Laravel 原始 SQL 查询,具有多次出现的命名绑定