Вы не обязаны использовать этот синтаксис.
from()
используется для указания таблицы , когда вы используете подзапрос. table()
используется для указания основной запрашиваемой таблицы.
Вы можете передать необязательный псевдоним в качестве второго параметра в обоих этих методах.
Примеры:
DB::table('users', 'u')->select('id as ID')->get();
// select id as ID from users as u
DB::table(function($sq) {
$sq->select('id')->from('users'); // must specify from when using subquery
})->select('id')->get();
// select id from (select id from users)
DB::table(function($sq) {
$sq->select('id'); // not specifying from leads to a bad query
})->select('id')->get();
// select id from (select id)
Если вы предпочитаете отделить запросы друг от друга, вы также можете сделать это
$subquery = DB::table('users')->select('id'); // $subquery will be a Query Builder instance you can pass to table() or from() instead of a Closure.
$query = DB::table($subquery, 'alias')->select('id');
$results = $query->get();
// select id from (select id from users) as alias
Мой совет: используйте метод toSql()
, чтобы убедиться, что ваши запросы верны . Начните с простого выполнения подзапроса.
SELECT
COUNT(*) streak,
SUM(amount) streakAmount,
MIN(date) startDate,
MAX(date) endDate,
dateMinusRow
FROM
# Start Subquery
(
SELECT
COUNT(*) amount,
date_trunc('day', start) date,
date_trunc('day', start) - INTERVAL '1' DAY * DENSE_RANK() OVER (ORDER BY date_trunc('day', start)) dateMinusRow
FROM sessions
WHERE user_id = ".$this->user->id."
GROUP BY date_trunc('day', start)
) groupedDays
# End Subquery
GROUP BY dateMinusRow
$subquery = DB::table('sessions')
->selectRaw(
"COUNT(*) as amount, "
."date_trunc('day', start) as date, "
."date_trunc('day', start) - INTERVAL '1' DAY * DENSE_RANK() OVER (ORDER BY date_trunc('day', start)) as dateMinusRow "
)
->where('user_id', $this->user->id)
->groupByRaw("date_trunc('day', start)");
// Verify the subquery is correct by dumping $subquery->toSql();
$query = DB::table($subquery, 'groupedDays')
->selectRaw(
"COUNT(*) as streak, "
."SUM(amount) as streakAmount, "
."MIN(date) as startDate, "
."MAX(date) as endDate, "
."dateMinusRow "
)
->groupBy('dateMinusRow');
// Verify the query is correct by dumping $query->toSql();
$results = $query->get();
Я не эксперт по postgres, поэтому предполагаю, что исходный запрос работает.
Изменить
from()
отсутствует в моем исходном ответе, потому что я не использую подзапрос Closure, а передаю экземпляр Query Builder. Вот как это выглядело бы, если бы я использовал from()
. На мой взгляд, работать с ним сложнее.
$query2 = DB::table(function($subquery) {
$subquery->from('sessions')
->selectRaw(
"COUNT(*) as amount, "
."date_trunc('day', start) as date, "
."date_trunc('day', start) - INTERVAL '1' DAY * DENSE_RANK() OVER (ORDER BY date_trunc('day', start)) as dateMinusRow "
)
->where('user_id', $this->user->id)
->groupByRaw("date_trunc('day', start)");
}, 'groupedDays')
->selectRaw(
"COUNT(*) as streak, "
."SUM(amount) as streakAmount, "
."MIN(date) as startDate, "
."MAX(date) as endDate, "
."dateMinusRow "
)
->groupBy('dateMinusRow');
// Verify the query is correct by dumping $query2->toSql();
$results = $query->get();
Сбрасывая оба запроса, единственное отличие, которое я, кажется, получаю в Sql, - это использование обратных кавычек.
>>> $query->toSql()
=> "select COUNT(*) as streak, SUM(amount) as streakAmount, MIN(date) as startDate, MAX(date) as endDate, dateMinusRow from (select COUNT(*) as amount, date_trunc('day', start) as d
ate, date_trunc('day', start) - INTERVAL '1' DAY * DENSE_RANK() OVER (ORDER BY date_trunc('day', start)) as dateMinusRow from "sessions" where "user_id" = ? group by date_trunc('day
', start)) as "groupedDays" group by "dateMinusRow""
>>> $query2->toSql()
=> "select COUNT(*) as streak, SUM(amount) as streakAmount, MIN(date) as startDate, MAX(date) as endDate, dateMinusRow from (select COUNT(*) as amount, date_trunc('day', start) as d
ate, date_trunc('day', start) - INTERVAL '1' DAY * DENSE_RANK() OVER (ORDER BY date_trunc('day', start)) as dateMinusRow from `sessions` where `user_id` = ? group by date_trunc('day
', start)) as `groupedDays` group by `dateMinusRow`"
Проблема с запросом может быть связана с одной из опций драйвера базы данных. Я не знаю точно, но, чтобы привести пример, некоторые запросы group by
не работают с Laravel, даже если сгенерированный код sql правильный , если только строгий режим не отключен в mysql драйвер.
Что касается того, почему я использую ключевое слово as
, то базы данных, с которыми я работаю, обычно либо mysql, либо postgresql, поэтому я предпочитаю использовать общую нотацию.