Построитель запросов Laravel DB - использование нескольких «от» с псевдонимами

У меня есть следующий запрос:

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?

Например:

  1. из cdrnew как cd_1 (Псевдонимы 1).
  2. из cdrnew как cd_2 (Псевдонимы 2).
  3. из cdrnew как cd_3 (Псевдонимы 3).
  4. ..... и так далее
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
0
340
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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();

Насколько я могу судить, генерируемые запросы одинаковы.

Если MySQL жалуется на предложение GROUP BY, убедитесь, что для строгого режима установлено значение false в config/database.php

IGP 14.12.2020 21:32

Другие вопросы по теме