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.
Related
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();
This query works fine when I was using Mysql, now that we've migrated to Postgres, it's giving an error. Where is the problem?
public function scopeClosestTo(\Illuminate\Database\Eloquent\Builder $query, array $coord = null)
{
if ($coord && isset($coord['longitude'], $coord['latitude'])) {
return $query->select([
'*',
'distance' => DB::table( 'offers as offers_temp' )->selectRaw(
'ST_Distance_Sphere(point(`longitude`, `latitude`), point(?, ?)) AS distance',
[$coord['longitude'], $coord['latitude']]
)->whereColumn('offers_temp.id', 'offers.id')
])
->withCount(['favoriteOffers'])
->where('published', '=', true)
->where('active', '=', true)
->whereNotNull('longitude')
->whereNotNull('latitude')
->whereDate('expires_at', '>', \Carbon\Carbon::now())
->orWhereNull('expires_at')
->orderBy('distance');
}
return $query;
}
Error:
"SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near ","\nLINE 1: ...ct , (select ST_Distance_Sphere(point(longitude, latitud...\n ^ (SQL: select *, (select ST_Distance_Sphere(point(longitude, latitude`), point(-43.3722344, -22.7867144)) AS distance from "offers" as "offers_temp" where "offers_temp"."id" = "offers"."id") as "distance", (select count() from "favorite_offers" where "offers"."id" = "favorite_offers"."offer_id" and "favorite_offers"."deleted_at" is null) as "favorite_offers_count" from "offers" where (("published" = 1 and "active" = 1 and "longitude" is not null and "latitude" is not null and "expires_at"::date > 2022-03-28 or "expires_at" is null) and "longitude" is not null and "latitude" is not null and exists (select * from "offer_categories" inner join "offers_offer_categories" on "offer_categories"."id" = "offers_offer_categories"."offer_category_id" where "offers"."id" = "offers_offer_categories"."offer_id" and "offers_offer_categories"."offer_category_id" in (1) and "offer_categories"."deleted_at" is null) and "to_companies" = 0 and "published" = 1 and "active" = 1 and "expires_at"::date > 2022-03-28 or "expires_at" is null) and "offers"."deleted_at" is null order by "distance" asc limit 15 offset 0)"
Your query uses backticks to escape column names, which works in MySQL. However, PostgreSQL uses double quotes to escape column names.
Change
point(`longitude`, `latitude`)
To
point("longitude", "latitude")
However, the words longitude and latitude are not reserved words in postgres, so there should be no reason you need to quote them.
See this article on the PostgreSQL wiki for more about moving from MySQL to PostgreSQL.
Please Help me i need pass this sql lines to a laravel syxtax to use
on customizable charts
Im using
https://github.com/ConsoleTVs/Charts
Sql Syntax:
SELECT
SUM(CASE WHEN status like 'Por Despachar' THEN 1 ELSE 0 END) AS Por_Despachar
,SUM(CASE WHEN status like 'Planificado' THEN 1 ELSE 0 END) AS Planificado
,SUM(CASE WHEN status like 'Despachado' THEN 1 ELSE 0 END) AS Despachado
FROM presupuesto
i want to add this parameter on interactive chart like this
enter image description here
This is my Controller:
<?php
namespace sisVentas\Http\Controllers;
use Illuminate\Http\Request;
use sisVentas\User;
use sisVentas\Http\Requests;
use Charts;
class EstadisticaController extends Controller
{
//
public function index()
{
$data = \DB::select("
SELECT
SUM(CASE WHEN status like 'Por Despachar' THEN 1 ELSE 0 END) AS Por_Despachar
,SUM(CASE WHEN status like 'Planificado' THEN 1 ELSE 0 END) AS Planificado
,SUM(CASE WHEN status like 'Despachado' THEN 1 ELSE 0 END) AS Despachado
FROM presupuesto
");
$chart = Charts::create('pie', 'highcharts')
// Setup the chart settings
->title("Resumen de Presupuestos Realizados")
// A dimension of 0 means it will take 100% of the space
// This defines a preset of colors already done:)
// You could always set them manually
// Setup the diferent datasets (this is a multi chart)
->labels(['Por Despachar', 'Despachado', 'Planificado'])
->values([65,10,20])
->dimensions(1000,500)
->responsive(false);
return dd($chart, $data);
}
}
Chart {#324 ▼
+id: null
+customId: null
+type: "pie"
+library: "highcharts"
+title: "Resumen de Presupuestos Realizados"
+element_label: "Element"
+labels: array:3 [▼
0 => "Por Despachar"
1 => "Despachado"
2 => "Planificado"
]
+values: array:3 [▼
0 => 65
1 => 10
2 => 20
]
+colors: []
+responsive: false
+gauge_style: "left"
+view: null
+region: "world"
#suffix: ""
+container: ""
+credits: false
+loader: true
+loader_duration: 500
+loader_color: "#000000"
+background_color: "inherit"
+template: "material"
+one_color: false
+legend: true
+x_axis_title: false
+y_axis_title: null
+"height": 500
+"width": 1000
}
array:1 [▼
0 => {#330 ▼
+"por_despachar": "3"
+"planificado": "1"
+"despachado": "0"
}
]
Maybe not direct answer but should be helpful
When you have any SQL query that is hard / impossible to convert into eloquent, just use DB facade.
$data = \DB::select("
SELECT
SUM(CASE WHEN status like 'Por Despachar' THEN 1 ELSE 0 END) AS Por_Despachar
,SUM(CASE WHEN status like 'Planificado' THEN 1 ELSE 0 END) AS Planificado
,SUM(CASE WHEN status like 'Despachado' THEN 1 ELSE 0 END) AS Despachado
FROM presupuesto
");
dd($data);
$chart = Charts::database($data, 'pie', 'highcharts')
->title('Amount subscribers')
->labels([Por_Despachar, Planificado, Despachado])
->values([$data[0]->Por_Despachar, $data[1]->Planificado, $data[2]->Despachado])
->dimensions(1000,500)
->responsive(true);
my table is like this and my collection is
$testmodel=Mage::getModel(test/p1)->getCollection();
my database table is below.
id cat_id rate p_id
1 1 4 1
2 1 2 1
3 1 3 2
4 2 5 3
5 2 3 1
and i want output like this in magento using collection
cat_id rate count_category
1 9 3
2 8 2
i found my PROBLEM correct code is below
$testmodel = Mage::getModel('test/p1')
->getCollection()
->addFieldToSelect('rate')
->addFieldToSelect('cat_id');
$testmodel ->getSelect()
->columns('SUM(rate) as total,COUNT(*) AS countCategory')
->group('cat_id');
if you use mysql4 as this model resource class then go to
Model/Mysql4/P1/Collection.php
here you need to add function
public function addGroupByCatId(){
$subSelect = clone $this->getSelect();
$CountsubSelect = clone $this->getSelect();
$subSelect->reset()
->from(array('rev' => 'youtable', 'SUM( rev.rate)')
->where('main_table.cat_id = rev.cat_id');
$CountsubSelect->reset()
->from(array('countrev' => 'youtable'),'COUNT(countrev.cat_id)')
->where('main_table.cat_id = countrev.cat_id');
$this->getSelect()
->join(
array('r' => 'youtable'),
'main_table.id = r.id',
array(
'review_sum' => new Zend_Db_Expr(sprintf('(%s)', $subSelect)),
'count_category' => new Zend_Db_Expr(sprintf('(%s)', $CountsubSelect)),
))
->group('main_table.cat_id');
return $this;
}
OR: Resouce as resource model then goto
if you use mysql4 as this model resource class then go to
Model/Resource/P1/Collection.php
here you need to add function
public function addGroupByCatId(){
$subSelect = clone $this->getSelect();
$CountsubSelect = clone $this->getSelect();
$subSelect->reset()
->from(array('rev' => 'youtable', 'SUM( rev.rate)')
->where('main_table.cat_id = rev.cat_id');
$CountsubSelect->reset()
->from(array('countrev' => 'youtable'),'COUNT(countrev.cat_id)')
->where('main_table.cat_id = countrev.cat_id');
$this->getSelect()
->join(
array('r' => 'youtable'),
'main_table.id = r.id',
array(
'review_sum' => new Zend_Db_Expr(sprintf('(%s)', $subSelect)),
'count_category' => new Zend_Db_Expr(sprintf('(%s)', $CountsubSelect)),
))
->group('main_table.cat_id');
return $this;
}
and final you get
$testmodel=Mage::getModel(test/p1)->getCollection();
$testmodel->addGroupByCatId();
i have three tables
cases,clients,attendance
in cases
id start_date end_date client_id status
1 2012-12-30 2013-01-30 1 new starts
2 2012-12-31 2013-01-31 2 probation
in clients
id Name dob gender status
1 TOM 1987-01-30 M A
2 JERRY 1985-01-31 F D
in attendance
id client_id date status
1 1 2013-01-30 A
2 1 2013-01-31 P
i need result like this
case_id case_start_date case_end_date client_id Name
att_date atte_status
1 2012-12-30 2013-01-30 1 TOM
2013-01-30,2013-01-31 A,P
is this possible? i'm a self learner and i don't have good idea in join query please any body help me....
try this..
$this->db->select('ca.*,ci.Name,a.date,a.status');
$this->db->from('cases'.' ca');
$this->db->join('clients'.' ci','ca.client_id=ci.id','left');
$this->db->join('attendance'.' a','a.client_id=ci.id','left');
return $this->db->get();
go through the user guide if u want to read more about join and active records...
Here's a very simple example to get you started with any number of join common fun for all
Construcor Code
Construct $joins as array:
$joins = array(
array(
'table' => 'table2',
'condition' => 'table2.id = table1.id',
'jointype' => 'LEFT'
),
);
Example function handling joins as an array:
public function get_joins($table, $columns, $joins)
{
$this->db->select($columns)->from($table);
if (is_array($joins) && count($joins) > 0)
{
foreach($joins as $k => $v)
{
$this->db->join($v['table'], $v['condition'], $v['jointype']);
}
}
return $this->db->get()->result_array();
}