我可以使用 Laravel 的查询构建器构建此查询吗?如果可以,那会是什么样子? (数据库::原始())

Can I build this query using Laravel's Query Builder and if so, what would that look like? (DB::raw())

我使用 Eloquent 和 Laravel 的查询构建器(混合)将结果查询放在一起,我想删除那个“混合”并使用 Laravel 的查询生成器。

使用 Laravel 的查询生成器,以下查询会是什么样子?

SELECT id,
  name,
  clicks_count,
  conversions_count,
  Round(((100 / clicks_count) * conversions_count), 2) AS conversion_rate,
  Cast((cost_integral / clicks_count) AS UNSIGNED) AS cpc_integral,
  Cast((Ifnull(revenue_integral, 0) / clicks_count) AS UNSIGNED) AS epc_integral,
  Cast(Ifnull(revenue_integral, 0) AS signed) AS revenue_integral,
  Cast(Ifnull(cost_integral, 0) AS UNSIGNED) AS cost_integral,
  Cast((Ifnull(revenue_integral, 0) - cost_integral) AS signed) AS profit_integral,
  Round((CASE
    WHEN(Ifnull(revenue_integral, 0) = 0 AND Ifnull(cost_integral, 0) = 0) THEN 0
    WHEN(Ifnull(revenue_integral, 0) = 0 AND Ifnull(cost_integral, 0) > 0) THEN -100
    WHEN(Ifnull(revenue_integral, 0) > 0 AND Ifnull(cost_integral, 0) = 0) THEN 100
    WHEN(Ifnull(revenue_integral, 0) > 0 AND Ifnull(cost_integral, 0) > 0) THEN ((revenue_integral / cost_integral) * 100)
  END), 2) AS roi
FROM
  (SELECT device_types.*,
    (SELECT Count(clicks.id)
      FROM clicks
      WHERE device_types.id = clicks.device_type_id
        AND clicks.created_at BETWEEN "2021-07-06 00:00:00" AND "2021-07-08 23:59:59"
        AND clicks.campaign_id = 2) AS clicks_count,
    (SELECT Count(conversions.id)
      FROM conversions
      INNER JOIN clicks ON clicks.id = conversions.click_id
      WHERE device_types.id = clicks.device_type_id
        AND conversions.created_at BETWEEN "2021-07-06 00:00:00" AND "2021-07-08 23:59:59"
        AND clicks.campaign_id = 2) AS conversions_count,
    (SELECT sum(clicks.cost_integral)
      FROM clicks
      WHERE device_types.id = clicks.device_type_id
        AND clicks.created_at BETWEEN "2021-07-06 00:00:00" AND "2021-07-08 23:59:59"
        AND clicks.campaign_id = 2) AS cost_integral,
    (SELECT sum(conversions.payout_integral)
      FROM conversions
      INNER JOIN clicks ON clicks.id = conversions.click_id
      WHERE device_types.id = clicks.device_type_id
        AND conversions.created_at BETWEEN "2021-07-06 00:00:00" AND "2021-07-08 23:59:59"
        AND clicks.campaign_id = 2) AS revenue_integral
FROM device_types
INNER JOIN clicks ON clicks.device_type_id = device_types.id
WHERE clicks.campaign_id = 2
GROUP BY device_types.id) AS metrics
ORDER BY clicks_count DESC

感谢您的帮助和时间。


编辑:

一个例子就够了——不需要重建整个查询。我只 post 编辑了它,因为在上一个线程中有人告诉我 post 整个 SQL 命令而不是一小部分(否则我肯定会缩短它)。

重要的是这些“子选择”并不简单DB::raw("(SELECT COUNT(clicks.id) FROM ...。相反,我想知道如何使用 Laravel 查询生成器来构建这些。

我就是这样做的:

use Illuminate\Database\Query\Builder;

$clicksCount = DB::table('clicks')
    ->whereColumn('device_types.id', 'clicks.device_type_id')
    ->whereBetween('clicks.created_at', [ "2021-07-06 00:00:00", "2021-07-08 23:59:59" ])
    ->where('clicks.campaign_id', 2)
    ->select(DB::raw('Count(clicks.id)');
$conversionsCount = DB::table('conversions')
    ->join('clicks', 'clicks.id', 'conversions.click_id')
    ->whereColumn('device_types.id', 'clicks.device_type_id')
    ->whereBetween('conversions.created_at', [ "2021-07-06 00:00:00", "2021-07-08 23:59:59" ])
    ->where('clicks.campaign_id', 2)
    ->select(DB::raw('Count(conversions.id)'));
$costIntegral = DB::table('clicks')
    ->whereColumn('device_types.id', 'clicks.device_type_id')
    ->whereBetween('clicks.created_at', [ "2021-07-06 00:00:00", "2021-07-08 23:59:59" ])
    ->where('clicks.campaign_id', 2)
    ->select(DB::raw('sum(clicks.cost_integral)'));
$revenueIntegral = DB::table('conversions')
    ->join('clicks', 'clicks.id', 'conversions.click_id')
    ->whereColumn('device_types.id', 'clicks.device_type_id')
    ->whereBetween('conversions.created_at', [ "2021-07-06 00:00:00", "2021-07-08 23:59:59" ])
    ->where('clicks.campaign_id', 2)
    ->select(DB::raw('sum(clicks.payout_integral)'));

$metrics = DB::table('device_types')
    ->join('clicks', 'clicks.device_type_id', 'device_types.id')
    ->where('clicks.campaign_id', 2)
    ->groupBy('device_types.id')
    ->select('device_types.*')
    ->selectSub($clicksCount, 'clicks_count')
    ->selectSub($conversionsCount, 'conversions_count')
    ->selectSub($costIntegral, 'cost_integral')
    ->selectSub($revenueIntegral, 'revenue_integral');

Builder::newQuery()->select(
    'id',
    'name',
    'clicks_count',
    'conversions_count'
)
->selectRaw('
  Round(((100 / clicks_count) * conversions_count), 2) AS conversion_rate,
  Cast((cost_integral / clicks_count) AS UNSIGNED) AS cpc_integral,
  Cast((Ifnull(revenue_integral, 0) / clicks_count) AS UNSIGNED) AS epc_integral,
  Cast(Ifnull(revenue_integral, 0) AS signed) AS revenue_integral,
  Cast(Ifnull(cost_integral, 0) AS UNSIGNED) AS cost_integral,
  Cast((Ifnull(revenue_integral, 0) - cost_integral) AS signed) AS profit_integral,
  Round((CASE
    WHEN(Ifnull(revenue_integral, 0) = 0 AND Ifnull(cost_integral, 0) = 0) THEN 0
    WHEN(Ifnull(revenue_integral, 0) = 0 AND Ifnull(cost_integral, 0) > 0) THEN -100
    WHEN(Ifnull(revenue_integral, 0) > 0 AND Ifnull(cost_integral, 0) = 0) THEN 100
    WHEN(Ifnull(revenue_integral, 0) > 0 AND Ifnull(cost_integral, 0) > 0) THEN ((revenue_integral / cost_integral) * 100)
  END), 2) AS roi')
->fromSub($metrics, 'metrics')
->orderByDesc('clicks_count')