#php #laravel #laravel-5 #laravel-query-builder
#php #laravel #laravel-5 #laravel-конструктор запросов
Вопрос:
У меня есть следующий запрос:
SELECT
cd_4.userfield,
COUNT( DISTINCT (Case When cd_4.disposition_Last = 'ANSWERED' Then cd_4.uniqueid ELSE NULL END) ) AS Answered_Count,
COUNT( DISTINCT (Case When cd_4.disposition_Last <> 'ANSWERED' Then cd_4.uniqueid ELSE NULL END) ) AS Not_Answered_Count
FROM (
SELECT
cd_2.Userfield,
cd_2.Start_Date,
cd_2.uniqueid,
cd_2.Row_Id_Max,
cd_3.disposition AS disposition_Last
FROM (
SELECT
cd_1.userfield,
cd_1.Start_Date,
cd_1.uniqueid,
MAX(cd_1.Row_Id) AS Row_Id_Max
FROM
cdrnew As cd_1
WHERE (
cd_1.Start_Date BETWEEN '2020-12-01' AND '2020-12-10'
)
AND cd_1.userfield = 'Inbound'
GROUP BY
cd_1.userfield,
cd_1.Start_Date,
cd_1.uniqueid
) AS cd_2
INNER JOIN cdrnew As cd_3
ON cd_3.Row_Id = cd_2.Row_Id_Max
WHERE (
cd_3.Start_Date BETWEEN '2020-12-01' AND '2020-12-10'
)
AND cd_3.userfield = 'Inbound'
) AS cd_4 ;
У меня есть 4 псевдонима, использованные выше для таблицы cdrnew с именами cd_1, cd_2, cd_3 и cd_4
Я хочу добиться того же, используя конструктор запросов laravel:
Я попытался выполнить следующий запрос laravel:
$sqlquery = DB::table('cdrnew')->select('cdrnew.userfield')
->addSelect(DB::raw('COUNT(DISTINCT (
Case When cdrnew.disposition = "ANSWERED" Then cdrnew.uniqueid ELSE NULL END
)) as Answered_Count'))
->addSelect(DB::raw('COUNT(DISTINCT (
Case When cdrnew.disposition <> "ANSWERED" Then cdrnew.uniqueid ELSE NULL END
)) as Not_Answered_Count'))
->addSelect(DB::raw('cdrnew.Start_Date, cdrnew.uniqueid, MAX(cdrnew.Row_Id) AS Row_Id_Max'))
->whereBetween('cdrnew.Start_Date', ["2020-12-12", "2020-12-15"])
->groupBy('userfield','Start_Date','uniqueid')
->join('cdrnew AS cd_1',"cdrnew.Row_Id", "=", "cd_1.Row_Id")
->limit(10)->get();
Но я могу создать только два псевдонима. Один из них по умолчанию из DB:: Table(cdrnew), а другой из join(cd_1). Как мы можем создать несколько операторов ‘from’ вместе с разными псевдонимами в laravel?
Например:
- из cdrnew как cd_1 (псевдонимы 1).
- из cdrnew как cd_2 (псевдонимы 2).
- из cdrnew как cd_3 (псевдонимы 3).
- ….. и так далее
Ответ №1:
Методы table
и from
работают аналогично. Они могут принимать 2 параметра: таблицу (которая может быть экземпляром Closure
или Builder
экземпляром) и псевдоним. Единственное отличие, насколько я могу судить, заключается в том, что это table
должен быть первый метод, вызываемый после DB::
Например, следующий запрос
SELECT * FROM (
SELECT * FROM table1 WHERE condition = "something"
) AS alias1
Может быть написано так, используя Closure
.
DB::table(function ($subquery) {
return $subquery->from('table1')->where('condition', 'something');
}, 'alias')
->get();
// Or using PHP7.4 short Closures
DB::table(fn($subquery) => $subquery->from('table1')->where('condition', 'something'), 'alias')->get();
Или как это, используя Builder
экземпляр.
$alias = DB::table('table1')->where('condition', 'something');
DB::table($alias, 'alias')->get();
Таким образом, ваш запрос может быть переведен следующим образом с помощью конструктора
$cd_2 = DB::table('cdrnew, cd_1')
->select(
'cd_1.userfield',
'cd_1.Start_Date',
'cd_1.uniqueid',
)
->selectRaw('MAX(cd_1.Row_Id) AS Row_Id_Max')
->whereBetween('cd_1.Start_Date', ['2020-12-01', '2020-12-10'])
->where('cd_1.userfield', 'Inbound')
->groupBy(
'cd_1.userfield',
'cd_1.Start_Date',
'cd_1.uniqueid'
);
$cd_4 = DB::table($cd_2, 'cd_2')
->select(
'cd_2.Userfield',
'cd_2.Start_Date',
'cd_2.uniqueid',
'cd_2.Row_Id_Max',
'cd_3.disposition AS disposition_Last'
)
->join('cdrnew AS cd_3', 'cd_3.Row_Id', '=', 'cd_2.Row_Id_Max')
->whereBetween('cd_3.Start_Date', ['2020-12-01', '2020-12-10'])
->where('cd3.userfield', 'Inbound');
$query = DB::table($cd_4, 'cd_4')
->select('cd_4.userfield')
->selectRaw('COUNT(DISTINCT(CASE WHEN cd_4.disposition_Last = "ANSWERED" THEN cd_4.uniqueid ELSE NULL END)) AS Answered_Count')
->selectRaw('COUNT(DISTINCT(CASE WHEN cd_4.disposition_Last <> "ANSWERED" THEN cd_4.uniqueid ELSE NULL END)) AS Not_Answered_Count');
// Uncomment next line to see the query produced. It should be the same you posted in your question.
// dd($query->toSql());
$results = $query->get();
Или как это с помощью Closures
$query = DB::table(function ($cd_4) {
return $cd_4->from(function ($cd_2) {
return $cd_2->from('cdrnew, cd_1')
->select(
'cd_1.userfield',
'cd_1.Start_Date',
'cd_1.uniqueid',
)
->selectRaw('MAX(cd_1.Row_Id) AS Row_Id_Max')
->whereBetween('cd_1.Start_Date', ['2020-12-01', '2020-12-10'])
->where('cd_1.userfield', 'Inbound')
->groupBy(
'cd_1.userfield',
'cd_1.Start_Date',
'cd_1.uniqueid'
);
}, 'cd_2')
->select(
'cd_2.Userfield',
'cd_2.Start_Date',
'cd_2.uniqueid',
'cd_2.Row_Id_Max',
'cd_3.disposition AS disposition_Last'
)
->join('cdrnew AS cd_3', 'cd_3.Row_Id', 'cd_2.Row_Id_Max')
->whereBetween('cd_3.Start_Date', ['2020-12-01', '2020-12-10'])
->where('cd3.userfield', 'Inbound');
}, 'cd_4')
->select('cd_4.userfield')
->selectRaw('COUNT(DISTINCT(CASE WHEN cd_4.disposition_Last = "ANSWERED" THEN cd_4.uniqueid ELSE NULL END)) AS Answered_Count')
->selectRaw('COUNT(DISTINCT(CASE WHEN cd_4.disposition_Last <> "ANSWERED" THEN cd_4.uniqueid ELSE NULL END)) AS Not_Answered_Count');
// Uncomment next line to see the query produced. It should be the same you posted in your question.
// dd($query->toSql());
$results = $query->get();
Насколько я могу судить, генерируемые запросы одинаковы.
Комментарии:
1. Если MySQL жалуется на предложение GROUP BY, убедитесь, что для строгого режима установлено значение
false
inconfig/database.php