[英]How to join multiple tables and group by and get top 2 from one table
我有 3 张桌子:isps、优惠和赞助商。
我有表统计信息有这 3 个表的外键。
我需要按目标、赞助商和报价对所有 isp 进行分组,但我只想获取在每个 isp、目标和赞助商中拥有最高 epc 的前 2 个报价。
Schema::create('isps', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
Schema::create('sponsors', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
Schema::create('offers', function (Blueprint $table) {
$table->id();
$table->string('offer_id')->nullable();
$table->string('name');
$table->foreignIdFor(Sponsor::class)->constrained()->cascadeOnUpdate()->cascadeOnDelete();
$table->timestamps();
});
Schema::create('statistics', function (Blueprint $table) {
$table->id();
$table->date('at')->nullable();
$table->foreignIdFor(Isp::class)->nullable();
$table->foreignIdFor(Sponsor::class)->nullable();
$table->foreignIdFor(Offer::class)->nullable();
$table->string('target')->default('NA');
$table->unsignedInteger('clicks')->default(0);
$table->unsignedDecimal('earns')->default(0);
$table->timestamps();
});
这是我的 function。 它可以工作,但它会获得所有优惠,而我想获得按 isps、目标、赞助商和优惠分组的顶级 epc 的前 2 个优惠。
epc=sum(statistics.earns)/ nullif(sum(statistics.clicks) group by isps, target and sponsors and offers
$stats = Statistic::query()->where('at', '>=', now()->subMonth())->selectRaw('
statistics.sponsor_id as sponsar_id,
sponsors.name as sponsor_name,
statistics.target,
statistics.isp_id as isp_id,
isps.name as isp_name,
statistics.offer_id as offer_id,
offers.name as offer_name, coalesce(sum(statistics.earns)/ nullif(sum(statistics.clicks)::numeric, 0),0) as epc
')
->join('sponsors', 'sponsors.id', '=', 'statistics.sponsor_id')
->join('offers', 'offers.id', '=', 'statistics.offer_id')
->join('isps', 'isps.id', '=', 'statistics.isp_id')
->groupBy(
'statistics.target', 'statistics.isp_id', 'isps.name', 'statistics.sponsor_id',
'sponsors.name', 'statistics.offer_id', 'offers.name')
->getQuery()
->get();
if ($stats->isEmpty()) {
return [];
}
return $stats->transform(fn($row) => [
'isp' => $row->isp_name,
'target' => $row->target,
'sponsor' => $row->sponsor_name,
'offer' => $row->offer_name,
'epc' => $row->epc,
])->toArray();
网络服务商 | 目标 | 赞助 | 优惠 | EPC |
---|---|---|---|---|
热信 | 垃圾邮件 | S1 | OF1 | 10 |
热信 | 垃圾邮件 | S1 | OF12 | 5 |
热信 | 垃圾邮件 | S2 | OF6 | 12 |
热信 | 垃圾邮件 | S2 | OF12 | 6 |
gmail | 收件箱 | S1 | OF16 | 9 |
gmail | 收件箱 | S1 | OF5 | 3 |
gmail | 收件箱 | S2 | OF5 | 12 |
gmail | 收件箱 | S2 | OF5 | 6 |
您可以只添加一个orderBy('')
子句以按照您认为合适的方式进行排序,然后->take(2)
到 select 只有两个项目
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.