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
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.
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.
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
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:
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);