第 0 步:缩进该查询,使其更易于使用
我为此使用了https://codebeautify.org/sqlformatter。结果如下:
SET
@row_num = 0;
SELECT
@row_num := @row_num + 1,
model.name,
date,
sum(a),
sum(b),
SUM(
SUM(b)
) OVER(
PARTITION BY model.name
ORDER BY
date ROWS BETWEEN 2 PRECEDING
AND CURRENT ROW
),
IF(
@row_num > 2,
SUM(
SUM(b)/ 3
) OVER(
PARTITION BY model.name
ORDER BY
date ROWS BETWEEN 2 PRECEDING
AND CURRENT ROW
),
NULL
)
FROM
table
INNER JOIN model ON table.id_model = model.id
WHERE
id_model = 1
GROUP BY
date
第 1 步:识别不同的语句。
您的查询(或查询)有 2 个语句。 SET 语句和 SELECT 语句。
第 2 步:如果可能,将语句翻译到查询生成器。
先从最短/更容易的开始
步骤 2.1:翻译SET 语句。
要运行我们不关心结果的语句(只是它运行),可以使用DB::statement()。这主要是复制 SQL。
DB::statement('SET @row_num = 0');
步骤 2.2:翻译SELECT 语句。
对于复杂的 SQL 查询,最简单的翻译方法是使用tinker 运行它们,并检查它们在使用toSql() 时是否相同。
- 创建一个临时 .php 文件:
touch myquery.php。
- 在临时 php 文件中写入正在进行的查询,以
->toSql(); 结束并转储结果。
- 通过
tinker运行它:php artisan tinker myquery.php
- 继续处理临时 php 文件中的查询
- 重复第 3 步和第 4 步,直到查询是您想要的。
再次,我们可以从简单的部分开始。
现在查询应该如下所示:
$query = DB::table('table')
->join('model', 'table.id_model', 'model.id')
->where('id_model', 1)
->groupBy('date')
->toSql();
至于选择的列;其中许多是聚合函数,因此需要使用selectRaw()。顾名思义,您几乎可以将原始 SQL 传递给它。您可以将所有内容放在一个 selectRaw() 中,但为了便于阅读,我更喜欢每列使用一个。
因此,最终查询如下所示:
$query = DB::table('table')
->selectRaw('@row_num := @row_num + 1')
->selectRaw('model.name')
->selectRaw('date')
->selectRaw('sum(a)')
->selectRaw('sum(b)')
->selectRaw('SUM(SUM(b)) OVER (PARTITION BY model.name ORDER BY date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)')
->selectRaw('IF(row_num > 2, SUM(SUM(b)/3) OVER (PARTITION BY model.name ORDER BY date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW), NULL)')
->join('model', 'table.id_model', 'model.id')
->where('id_model', 1)
->groupBy('date')
->toSql();
在那里,应该完成。
第 3 步:清理
步骤 3.1:将查询复制到您的控制器或您需要使用它们的任何地方。
DB::statement('SET @row_num = 0');
$results = DB::table('table')
->selectRaw('@row_num := @row_num + 1')
->selectRaw('model.name')
->selectRaw('date')
->selectRaw('sum(a)')
->selectRaw('sum(b)')
->selectRaw('SUM(SUM(b)) OVER (PARTITION BY model.name ORDER BY date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)')
->selectRaw('IF(row_num > 2, SUM(SUM(b)/3) OVER (PARTITION BY model.name ORDER BY date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW), NULL)')
->join('model', 'table.id_model', 'model.id')
->where('id_model', 1)
->groupBy('date')
->get();
步骤 3.2:删除临时 php 文件。