How to use withCount by year of birth? - laravel

I have a users table, I need to pull out the count by year of birth.
SQL example:
-- years = [1999, 1997, 1996, ..., 1990] example
SELECT u.city, count(*) -- all count
SUM(IF(u.born_date between '1999-01-01' and '1999-12-31', 1, 0)) as '1999',
SUM(IF(u.born_date between '1998-01-01' and '1998-12-31', 1, 0)) as '1999',
SUM(IF(u.born_date between '1997-01-01' and '1997-12-31', 1, 0)) as '1999'
-- some more years
FROM users u
GROUP BY u.city;
How to do it in Laravel?
upd: I need to take users from another table, while I decided it like this:
$years = [1999, 1997, 1996]; // example
$byYearQueries = [];
$cities = City::query()->where('active', 1);
foreach ($years as $year) {
$byYearQueries['users as y' . $year] = function (Builder $query) use ($year) {
$query->whereHas(
'users',
function ($q) use ($year) {
/** #var Builder $q */
$q
->where(
'born_date',
'>=',
Carbon::make($year . '-01-01')->timestamp
)
->where(
'born_date',
'<=',
Carbon::make($year . '-12-31')->timestamp
);
}
);
};
}
$result = $cities->withCount($byYearQueries)->get();
result: y1999: 20, y1997: 15 ...

Maybe you could try this :
$stats = User::select(DB::raw('city, YEAR(born_date) as year_of_birth, count(*) as count'))
->groupBy(DB::raw('city, YEAR(born_date)'))
->toBase()
->get();
you can if you want create an array with year_of_birth => number of users :
$stats->groupBy('city')->map->pluck('count', 'year_of_birth');
you will have then :
'London' => [
1999 => 204,
2000 => 301,
2001 => 2,
],
'Paris' => [
1999 => 44,
2001 => 30,
...
]
And you will not have to make a query for every year

You can try it:
DB::table('users')
->selectRaw("users.city,
count(*) AS allCount,
(CASE WHEN users.born_date BETWEEN '1999-01-01' AND '1999-12-31' THEN 1 ELSE 0 END) AS year1999),
(CASE WHEN users.born_date BETWEEN '1998-01-01' AND '1998-12-31' THEN 1 ELSE 0 END) AS year1998),
(CASE WHEN users.born_date BETWEEN '1997-01-01' AND '1997-12-31' THEN 1 ELSE 0 END) AS year1997)")
->groupBy('users.city')
->get();

Related

Count every records that exist on each program per college using Laravel

I have this query that produces all the College program.
$report = DB::table('college')
->leftJoin('program', 'program.college_id', '=', 'college.college_id')
->leftJoin('application', 'application.college_id', 'college.college_id')
->leftJoin('application_status', 'application_status.id', '=', 'application.status')
->select('college.college_name', 'program.program_name', 'program.program_id', 'program.track', 'application.acad_year', 'application.semester', 'application_status.name as name',
// DB::raw('SUM(application.application_no) as total'),
DB::raw('COUNT(program.college_id = '.$request->college_id.') as total'),
)
->where([
'application.acad_year' => $request->acad_year,
'application.semester' => $request->semester,
'college.college_id' => $request->college_id,
'application.status' => $request->status_id
])
->groupBy('program.program_id')
->get();
What I want is, I want to get all the "Applicants" each "Program" by Colleges. My problem is, the count of all applicants on each programs by colleges.

Erro Nova ChartJs SQL Generator when using PostgreSQL

Describe the bug
I'm trying to generate a chart, however when I pass the parameter "filter" to SQL Builder, more specifically the file "TotalRecordsController" assembles the query as if I were using MySQL, instead of mounting it for PostgreSQL.
Laravel: 8.40
PHP: 7.4
PostgreSQL: 12
Nova: 3.30
ChartJS: 0.3.5
Linux Mint
Chrome
My Code:
public function cards(Request $request)
{
$process_statuses= [
["label"=>"INITIAL" ,"color" => "#007BFF"],
['label'=>'CONVERTED' ,'color' => '#28A645'],
['label'=>'ERROR' ,'color' => '#DC3544'],
['label'=>'WAITING_TO_ERICH' ,'color' => '#17A2B8'],
['label'=>'WAITING_TO_CONVERT','color' => '#17A2B8']
];
$series = [];
foreach ($process_statuses as $status){
$new_serie = [
'label' => $status['label'],
'filter'=>[
'key'=>'process_status',
'value'=>$status['label']
],
'barPercentage' => 0.5,
'backgroundColor' => $status['color'],
];
$series = [...$series,$new_serie];
}
return [
(new BarChart())
->title('Today Status')
//->model(\App\Models\GoogleOfflineConversion::class)
->model('\App\Models\FacebookOfflineConversion')
->series($series)
->options([
'btnRefresh'=>true,
'uom' => 'hour',
])->width('full'),
];
}
Error:
SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "'INITIAL'"
LINE 1: ... process_status = 'INITIAL' then 1 else 0 end) as 'INITIAL',...
^ (SQL: select HOUR(facebook_offline_conversions.created_at) AS cat, HOUR(facebook_offline_conversions.created_at) AS catorder, sum(1) counted, SUM(CASE WHEN process_status = 'INITIAL' then 1 else 0 end) as 'INITIAL', SUM(CASE WHEN process_status = 'CONVERTED' then 1 else 0 end) as 'CONVERTED', SUM(CASE WHEN process_status = 'ERROR' then 1 else 0 end) as 'ERROR', SUM(CASE WHEN process_status = 'WAITING_TO_ERICH' then 1 else 0 end) as 'WAITING_TO_ERICH', SUM(CASE WHEN process_status = 'WAITING_TO_CONVERT' then 1 else 0 end) as 'WAITING_TO_CONVERT' from "facebook_offline_conversions" where facebook_offline_conversions.created_at >= 2021-10-28 00:00:00 group by "catorder", "cat" order by "catorder" asc)
Migration of the my database:
Schema::create('facebook_offline_conversions', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->foreignUuid('company_id')->nullable();
$table->integer('refer_site_id')->nullable();
$table->foreignUuid('site_id')->nullable();
$table->foreignUuid('facebook_ads_site_credential_id')->nullable();
$table->string('crm_order_id')->nullable();
$table->string('fbc')->nullable();
$table->longText('document_number')->nullable();
$table->longText('email')->nullable();
$table->longText('phone_number')->nullable();
$table->float('value')->nullable();
$table->string('currency')->nullable();
$table->longText('city')->nullable();
$table->longText('state')->nullable();
$table->longText('zip_code')->nullable();
$table->longText('country')->nullable();
$table->timestamp('conversion_time')->nullable();
$table->longText('ip_address')->nullable();
$table->longText('browser')->nullable();
$table->string('process_status')->nullable();
$table->integer('tries')->nullable();
$table->boolean('approximated')->default(false);
$table->json('conversion_response')->nullable();
$table->timestamps();
});
I'm resolving this problem. The solution is to change the file "src/api/TotalRecordsController" inside the folder "~/vendor/coroowicaksono/chart-js-integration" so that it suits PostgreSQL.

How to Convert this Query to Eloquent or Query Builder?

I have a query like this. How should I convert it into a eloquent or query builder
SELECT
x.MATERIAL_ID,
(SELECT TAPET_NAME FROM MA_TAPE_TYPE WHERE TAPET_CODE = x.MATERIAL_TYPE) as media_type,
(SELECT TAPEF_NAME FROM MA_TAPE_FORMAT WHERE TAPEF_CODE = x.MATERIAL_FORMAT) as media_format,
STOCK_MATERIAL_EPI.HOUSE_NO,
x.TXN_DATE,
STOCK_MATERIAL_EPI.PROGRAM_NAME,
CASE WHEN x.iden_flag = 'P' THEN STOCK_MATERIAL_EPI.epi_title WHEN x.iden_flag = 'C'
THEN STOCK_MATERIAL_EPI.prod_version_name WHEN x.iden_flag = 'M' THEN STOCK_MATERIAL_EPI.promo_name
END as episode_title,
PUR_EPISODE_HDR.EPI_NO,
(SELECT MAX (last_date) FROM run_master WHERE run_master.row_id_epi = PUR_EPISODE_HDR.row_id AND
run_master.run_aired = 'Y') as last_tx,
x.REMARKS,
x.LOCATION_ID as shelf_no,
stock_material_slag.remarks as short_list
FROM STOCK_MATERIAL x
LEFT JOIN STOCK_MATERIAL_EPI ON x.MATERIAL_ID = STOCK_MATERIAL_EPI.MATERIAL_ID
LEFT JOIN stock_material_slag ON x.MATERIAL_ID = stock_material_slag.MATERIAL_ID
LEFT JOIN PUR_EPISODE_HDR ON STOCK_MATERIAL_EPI.ROW_ID_EPI = PUR_EPISODE_HDR.ROW_ID
I'm confused as to how to convert them. Can someone help me.
I tried to write like this.
But it doesn't work,
$materials = DB::connection('oracle')
->table('STOCK_MATERIAL AS x')
->select('x.MATERIAL_ID',
DB::raw("(SELECT TAPET_NAME FROM MA_TAPE_TYPE WHERE TAPET_CODE = x.MATERIAL_TYPE) as MEDIA_TYPE"),
DB::raw("(SELECT TAPEF_NAME FROM MA_TAPE_FORMAT WHERE TAPEF_CODE = x.MATERIAL_FORMAT) as MEDIA_FORMAT"),
'x.TXN_DATE',
'y.HOUSE_NO', 'y.PROGRAM_NAME',
DB::raw("(CASE WHEN x.IDEN_FLAG = 'P' THEN z.EPI_TITLE WHEN x.IDEN_FLAG = 'C' THEN z.PROD_VERSION_NAME WHEN x.IDEN_FLAG = 'M' THEN z.PROMO_NAME END as EPISODE_TITLE)"),
'w.EPI_NO',
DB::raw("(SELECT MAX (LAST_DATE) FROM RUN_MASTER WHERE RUN_MASTER.ROW_ID_EPI = w.ROW_ID AND RUN_MASTER.RUN_AIRED = 'Y') as LAST_TX"),
'z.REMARKS',
'x.LOCATION_ID as SHELF_NO',
'z.REMARKS'
)
->leftJoin('STOCK_MATERIAL_EPI AS y', 'y.MATERIAL_ID', '=', 'x.MATERIAL_ID')
->leftJoin('STOCK_MATERIAL_SLAG AS z', 'z.MATERIAL_ID', '=', 'x.MATERIAL_ID')
->leftJoin('PUR_EPISODE_HDR AS w', 'w.ROW_ID', '=', 'y.ROW_ID_EPI')
What else do I write right?
You would need to define eloquent models and then use with(). Documentation can be found at the link below: https://laravel.com/docs/7.x/eloquent-relationships#constraining-eager-loads
example
StockMaterial::with([
'maTapeType' => function($query) {
$query->get('name')
})
])
For Query Builder you DB::raw and DB::leftJoin to create the same query.
DB::from('STOCK_MATERIAL')
->selectRaw([
'TAPET_NAME as media_type',
'CASE WHEN x.iden_flag = "P" THEN STOCK_MATERIAL_EPI.epi_title
WHEN x.iden_flag = "C" THEN STOCK_MATERIAL_EPI.prod_version_name
WHEN x.iden_flag = "M" THEN STOCK_MATERIAL_EPI.promo_name
END as episode_title',
])
->leftJoin('MA_TAPE_TYPE', 'TAPET_CODE', 'STOCK_MATERIAL.MATERIAL_TYPE')
https://laravel.com/docs/7.x/queries#raw-expressions
https://laravel.com/docs/7.x/queries#joins

laravel Maatwebsite validate sum multi column

hi im using Maatwebsite with laravel everything working so good so far ..
but i want to update excel like this ..
number date amount
1 2020-01-01 10
1 2020-01-01 -5
1 2020-01-01 -5
2 2020-02-02 20
2 2020-02-02 -20
3 2020-03-03 50
3 2020-03-03 -50
3 2020-03-03 40
3 2020-03-03 -40
what i want thats the sum of the amount with number 1 sould return 0 or end the import
number date amount
1 2020-01-01 10
1 2020-01-01 -5
1 2020-01-01 -5
how can i check this (10 + -5 + -5 == 0) or fail
and for 2 and 3 ect ..
thanks a lot
I explained all the steps in comments but I will explain here as well.
When you loop through each row, you first need to grab all the rows where number field is 1, 2 or 3, what ever the number is currently in the iteration.
In this case, the first loop results will be:
number date amount
1 2020-01-01 10
1 2020-01-01 -5
1 2020-01-01 -5
Then you sum (add up) the values from the amount column.
In this case, it will sum like this:
10
-5
-5
-----
0
If the answer is not 0, take the current sheet ($sheet) and return what you currently have, to be exported.
Full class:
...
use Maatwebsite\Excel\Concerns\FromArray;
class ExampleExport implements FromArray
{
public function array() : array
{
// EXAMPLE hardcoded data for the purpose of this demo
$rows = [
[
'number' => 1,
'date' => '2020-01-01',
'amount' => 10
],
[
'number' => 1,
'date' => '2020-01-01',
'amount' => -5
],
[
'number' => 1,
'date' => '2020-01-01',
'amount' => -5
],
[
'number' => 2,
'date' => '2020-02-02',
'amount' => 20
],
[
'number' => 2,
'date' => '2020-02-02',
'amount' => -20 // <-------- Change this to -21 to test
],
[
'number' => 3,
'date' => '2020-03-03',
'amount' => 50
],
[
'number' => 3,
'date' => '2020-03-03',
'amount' => -50
],
[
'number' => 3,
'date' => '2020-03-03',
'amount' => 40
],
[
'number' => 3,
'date' => '2020-03-03',
'amount' => -40
],
];
// EXAMPLE hardcoded data for the purpose of this demo
$rows = collect($rows);
// You probably going to get this from your database so should look like this:
// $rows = \App\Model::all(['number', 'date', 'amount']); // OR below
// $rows = DB::table('examples')->select(['number', 'date', 'amount'])->get();
// Blank sheet
$sheet = [];
foreach ($rows as $row) {
// Get all the rows where the `number` field has the same value,
// for example 1, 2, or 3, then sum the `amount` field (add up).
//
// If the amount does not add up to 0, stop and return what you currently got
if ($rows->where('number', $row['number'])->sum('amount') !== 0) {
return $sheet;
}
// Else, add them to the sheet and continue.
$sheet[] = $row;
}
return $sheet;
}
}
Results:
When amount adds up to 0:
When amount does not add up to 0:

Laravel - Group By same day ( Mon , Tue , etcc)

I have the following table:
TABLE:schedule
id day name
-----------------------------
1 Mon test
2 Mon hello
3 Tue another
4 Tue here
5 Wed go
I have a Laravel model for this , so I am trying to group day
here is the result I would like to have as an object:
['Mon']-> array[0]='name'=>test,
array[1]='name'=>hello,
['Tue']-> array[0]='name'=>another,
array[1]='name'=>here,
here is my code in the HomeController:
$schedule = DB::table('schedule')
->select('*')
->groupBy('day')
->get();
This is not working only showing one day and not grouping them , anyone knows why?
Thanks
This is a little bit complicated problem. I think, you are looking something like the following:
$schedules = DB::table('schedule')
->selectRaw('id, day, group_concat(name) as name')
->groupBy('day')
->get();
$data = array();
foreach ($schedules as $schedule) {
$data[$schedule->day][] = explode(",",$schedule->name);
}
var_dump($data);
output:
array (size=3)
'Mon' =>
array (size=1)
0 =>
array (size=12)
0 => string 'test' (length=4)
1 => string 'hello' (length=5)
'Tue' =>
array (size=1)
0 =>
array (size=3)
0 => string 'another' (length=6)
1 => string 'here' (length=4)
'Wed' =>
array (size=1)
0 =>
array (size=1)
0 => string 'go' (length=2)
Edit:
Do another group_concat for extra field.
$schedules = DB::table('schedule')
->selectRaw('id, day, group_concat(name) as name, group_concat(city) as city')
->groupBy('day')
->get();
$data = array();
foreach ($schedules as $schedule) {
$data[$schedule->day]['name'] = explode(",",$schedule->name);
$data[$schedule->day]['city'] = explode(",",$schedule->city);
}
var_dump($data);

Resources