Laravel join tables and concatenate rows - mysql

So I have two tables, organizations and contacts. Both tables have column "email", what I need to do is to keep the name of organization, but in email column concatenate all emails (organization's + all contact emails).
Here are some versions that I tried with no luck
1) this one doesn't group:
$customers = DB::table('customers')
->whereRaw('LENGTH(customers.email) > 4')
->select([
'customers.id',
'customers.name',
'customers.email'
]);
$contacts = DB::table('contacts')
->whereRaw('LENGTH(contacts.email) > 4')
->leftJoin('customers', 'contacts.customer_id', '=', 'customers.id')
->select([
'customers.id',
'customers.name',
'contacts.email'
]);
return $customers
->union($contacts)
->select([
'id',
'name',
DB::raw('GROUP_CONCAT(DISTINCT email, ", ") AS emails'),
])
->groupBy('id')
->get();
2) this one is actually pretty close, but it doesn't filter out entries where neither contact or customer entires have DB::raw('LENGTH(email) > 4')
return $customers = DB::table('customers')
->leftJoin('contacts', 'contacts.customer_id', '=', 'customers.id')
->select([
'customers.id',
'customers.name',
'registration',
DB::raw('GROUP_CONCAT(DISTINCT contacts.email, ", ") AS contact_emails'),
'customers.email'
])
->groupBy('customers.id')
->get();
3) I tried to get closer with subqueries (I know it would only filter out contacts with no emails)
3.1) Trying subquery 1 results in error: JoinClause::whereRaw() doesn't exist
return $customers = DB::table('customers')
->leftJoin('contacts', function($join) {
$join->on('contacts.customer_id', '=', 'customers.id')
->whereRaw('LENGTH(email) > 4');
})...
3.2) This one produces the syntax error below:
return $customers = DB::table('customers')
->leftJoin('contacts', function($join) {
$join->on('contacts.customer_id', '=', 'customers.id')
->where(DB::raw('LENGTH(email) > 4'));
})
1/2 PDOException in Connection.php line 333: SQLSTATE[42000]: Syntax
error or access violation: 1064 You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the
right syntax to use near '? group by customers.id' at line 1
2/2 QueryException in Connection.php line 713: SQLSTATE[42000]: Syntax
error or access violation: 1064 You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the
right syntax to use near '? group by customers.id' at line 1 (SQL:
select customers.id, customers.name, registration,
GROUP_CONCAT(DISTINCT contacts.email, ", ") AS contact_emails,
customers.email from customers left join contacts on
contacts.customer_id = customers.id and LENGTH(contacts.email)
4 group by customers.id)
3.3) some examples say I should do it this way, but this produces the error Not enough arguments for the on clause.
return $customers = DB::table('customers')
->leftJoin('contacts', function($join) {
$join->on('contacts.customer_id', '=', 'customers.id');
$join->on(DB::raw('LENGTH(contacts.email) > 4'));
})

This works for me. No syntax errors and filters out contacts with length less than 4 characters:
DB::table('customers')
->leftJoin('contacts', function ($join) {
$join->on('contacts.customer_id', '=', 'customers.id')
->where(DB::raw('length(contacts.email)'), '>', 4);
})
->select([
'customers.id',
'customers.name',
DB::raw('group_concat(distinct contacts.email separator ", ") AS contact_emails'),
])
->groupBy('customers.id')
->get();
Tested in Laravel 5.3.26, MySQL 5.6.20 (no strict mode).

Related

SQLSTATE[HY093]: Invalid parameter number happens for a left join

$teacherStats = DB::table( DB::raw("({$payableContracts->toSql()}) as payable") )
->select('payable.teacher_id')
->selectRaw("CONCAT(first_name, ' ', last_name) as full_name,
SUM(total_direct_benefit + total_indirect_benefit) AS total_benefit,
SUM(teachers_direct_share + teachers_indirect_share) as teachers_share"
)
->selectRaw("DATE('$wageFrom') as wage_from, DATE('$wageTo') as wage_to")
->mergeBindings($payableContracts)
->join('users', 'payable.teacher_id', 'users.id')
->groupBy('payable.teacher_id')
$result = DB::table(DB::raw("({$teacherStats->toSql()}) as stats"))
->leftJoin('teacher_wages', function ($join) use ($wageFrom, $wageTo){
$join->on('stats.teacher_id', '=', 'teacher_wages.teacher_id')
->where('teacher_wages.from', $wageFrom)
->where('teacher_wages.to', $wageTo)
->where('teacher_wages.contracts_type', 'percentage-based');
});
I have $teacherStats as a query and when I get and dd() the result of it, it just works fine. This query is a complicated one but the result is as simple as:
[▼
0 => {#591 ▼
+"teacher_id": 2
+"full_name": "Tom Cruz"
+"total_benefit": "126000"
+"teachers_share": "25200"
+"wage_from": "2020-04-01"
+"wage_to": "2020-04-03"
}
1 => {#594 ▼
+"teacher_id": 5
+"full_name": "John Reno"
+"total_benefit": "296000"
+"teachers_share": "103600"
+"wage_from": "2020-04-01"
+"wage_to": "2020-04-03"
}
]
The problem is with the above $result query which converts $teacherStats to sql as an alias and does a simple join with another table. I get this error:
SQLSTATE[HY093]: Invalid parameter number
without a clue to what parameter and number it refers to.

Error trying to turn raw sql into laravel query builder

I am trying to turn this very long raw sql into laravel query builder and encounter an error.
This is the original raw sql
sql = "select d.doc_Code,d.seq,p.seq2,d.product_code,d.name_t,d.dwg_file,p.book,concat(p.book,'-',p.seq) as job_book,h.sale_code,h.sale_name,h.ref_code,h.ref_name,h.priority,p.code,p.in_time,wt_date,p.job_status,d.status,DATEDIFF(now(),p.in_time) as gdays,DATEDIFF(h.due_date,now()) as gdue_days,h.due_date,h.start_date as start_datex from jt_p as p inner join jt_d as d on (p.doc_code=d.doc_code and p.book=d.book and p.seq=d.seq and p.in_time is not null and p.wt_date is null and p.job_status not in('Z','C') and p.code<>'M' and d.status <>'C') inner join jt_h as h on(h.doc_code =p.doc_code and h.book=p.book)"
Here is the laravel query builder:
$jt_p = DB::table('jt_p')
->join('jt_d', function($join){
$join->on('jt_p.doc_code', '=', 'jt_d.doc_code');
$join->on('jt_p.book','=','jt_d.book');
$join->on('jt_p.seq','=','jt_d.seq');
})
->where('jt_p.in_time','!=','')
->where('jt_p.wt_time','=','')
->where('jt_p.job_status',DB::raw('not in ("Z","C")'))
->where('jt_p.code','!=','M')
->where('jt_d.status','!=','C')
->join('jt_h', function($join){
$join->on('jt_h.doc_code', '=', 'jt_p.doc_code');
$join->on('jt_p.book','=','jt_h.book');
})
->select('jt_d.doc_code','jt_d.seq','jt_p.seq2','jt_d.product_code','jt_d.name_t','jt_d.dwg_file','jt_p.book',
'jt_h.sale_code','jt_h.sale_name','jt_h.ref_code','jt_h.ref_name','jt_h.priority','jt_p.code','jt_p.in_time','jt_p.wt_time',
'jt_p.job_status','jt_d.status',DB::raw("DATEDIFF(now(),jt_p.in_time) as gdays"),
DB::raw("DATEDIFF(jt_h.due_date,now()) as gdue_days"),
'jt_h.due_date','jt_h.start_date as start_datex')
->get();
return $jt_p;
This is the error message:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'not in ("Z","C") and `jt_p`.`code` != ? and `jt_d`.`status` != ?' at line 1 (SQL: select `jt_d`.`doc_code`, `jt_d`.`seq`, `jt_p`.`seq2`, `jt_d`.`product_code`, `jt_d`.`name_t`, `jt_d`.`dwg_file`, `jt_p`.`book`, `jt_h`.`sale_code`, `jt_h`.`sale_name`, `jt_h`.`ref_code`, `jt_h`.`ref_name`, `jt_h`.`priority`, `jt_p`.`code`, `jt_p`.`in_time`, `jt_p`.`wt_time`, `jt_p`.`job_status`, `jt_d`.`status`, DATEDIFF(now(),jt_p.in_time) as gdays, DATEDIFF(jt_h.due_date,now()) as gdue_days, `jt_h`.`due_date`, `jt_h`.`start_date` as `start_datex` from `jt_p` inner join `jt_d` on `jt_p`.`doc_code` = `jt_d`.`doc_code` and `jt_p`.`book` = `jt_d`.`book` and `jt_p`.`seq` = `jt_d`.`seq` inner join `jt_h` on `jt_h`.`doc_code` = `jt_p`.`doc_code` and `jt_p`.`book` = `jt_h`.`book` where `jt_p`.`in_time` != and `jt_p`.`wt_time` = and `jt_p`.`job_status` = not in ("Z","C") and `jt_p`.`code` != M and `jt_d`.`status` != C)
Change this line of code
->where('jt_p.job_status',DB::raw('not in ("Z","C")'))
to
->whereNotIn('jt_p.job_status',["Z","C"])
You need also to use IsNull IsNotNull
$jt_p = DB::table('jt_p')
->join('jt_d', function($join){
$join->on('jt_p.doc_code', '=', 'jt_d.doc_code');
$join->on('jt_p.book','=','jt_d.book');
$join->on('jt_p.seq','=','jt_d.seq');
})
->whereNotNull('jt_p.in_time')
->whereNull('jt_p.wt_time')
->whereNotIn('jt_p.job_status',["Z","C"])
->where('jt_p.code','!=','M')
->where('jt_d.status','!=','C')
->join('jt_h', function($join){
$join->on('jt_h.doc_code', '=', 'jt_p.doc_code');
$join->on('jt_p.book','=','jt_h.book');
})
->select('jt_d.doc_code','jt_d.seq','jt_p.seq2','jt_d.product_code','jt_d.name_t','jt_d.dwg_file','jt_p.book',
'jt_h.sale_code','jt_h.sale_name','jt_h.ref_code','jt_h.ref_name','jt_h.priority','jt_p.code','jt_p.in_time','jt_p.wt_time',
'jt_p.job_status','jt_d.status',DB::raw("DATEDIFF(now(),jt_p.in_time) as gdays"),
DB::raw("DATEDIFF(jt_h.due_date,now()) as gdue_days"),
'jt_h.due_date','jt_h.start_date as start_datex')
->get();
return $jt_p;

how to use MIN and MAX sql query in Laravel Eloquent

i want to use min and max laravel elaquent at the same line, is that posible?
Appointmentsetting::where('Day','=',1)
->whereIn('PersonID', function ($query) {
$query->select('p.id')
->from('users as p')
->join('appointmentsettings as aps', 'aps.PersonID', '=', 'p.id')
->where('p.active', '=', 1)
->where('aps.CompanyID', '=', 1)
->orWhereIn('aps.PersonID', function ($query2) {
$query2->select('cps.user_id')
->from('companypersonstructs as cps')
->where('cps.CompanyID', '=', 1);
})
->groupBy('aps.PersonID');
})
->where('active', '=', 1)
->select(\DB::raw("SELECT MIN(StartFrom) AS StartFrom, MAX(EndTo) AS EndTo"));
->get();
i got error
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an
error in your SQL syntax; check the manual that corresponds to your
MariaDB server version for the right syntax to use near 'SELECT
MIN(StartFrom) AS StartFrom, MAX(EndTo) AS EndTo from
`appointmentsetting' at line 1
->selectRaw(" MIN(StartFrom) AS StartFrom, MAX(EndTo) AS EndTo");
please put above query and try. the main problem in your query is you are using select two time there is no need for write select inside select or selectRaw
for more about raw query click here
Appointmentsetting::where('Day','=',1)
->whereIn('PersonID', function ($query) {
$query->select('p.id')
->from('users as p')
->join('appointmentsettings as aps', 'aps.PersonID', '=', 'p.id')
->where('p.active', '=', 1)
->where('aps.CompanyID', '=', 1)
->orWhereIn('aps.PersonID', function ($query2) {
$query2->select('cps.user_id')
->from('companypersonstructs as cps')
->where('cps.CompanyID', '=', 1);
})
->groupBy('aps.PersonID');
})
->where('active', '=', 1)
->select(\DB::raw("MIN(StartFrom) AS StartFrom, MAX(EndTo) AS EndTo"));
->get();

Laravel 5.4 Error when Joining two tables

I need to join two tables in laravel model. Here is my query,
$id="1002";
$resultsInCalls = DB::table('qlog')
->select('user_master.fname','user_master.lname','qlog.data2')
->whereDate('created', '=', date('Y-m-d')) // this day
->join('qlog', 'qlog.agent', '=', 'user_master.sip_id')
->where('agent', '=', $id)
->where(function ($query) {
$query->where('event', '=', 'COMPLETEAGENT')
->orWhere('event', '=', 'COMPLETECALLER');
})
->take(5)
->get();
But I run this query I get following error.
SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'qlog' (SQL: select `user_master`.`fname`, `user_master`.`lname`, `qlog`.`data2` from `qlog` inner join `qlog` on `qlog`.`agent` = `user_master`.`sip_id` where date(`created`) = 2017-11-29 and `agent` = 1002 and (`event` = COMPLETEAGENT or `event` = COMPLETECALLER) limit 5)
I read related questions. But I can't figure it out. How to fix this error.
Here I get it done,
$resultsInCalls = DB::table('qlog')
->join('user_master as user_table', 'qlog.agent', '=', 'user_table.sip_id')
->select('user_table.fname','user_table.lname','qlog.data2')
->whereDate('created', '=', date('Y-m-d')) // this day
->where('agent', '=', $id)
->where(function ($query) {
$query->where('event', '=', 'COMPLETEAGENT')
->orWhere('event', '=', 'COMPLETECALLER');
})
->take(5)
->get();

laravel between two dates query error Syntax error

please help me in my query . I am currently getting query error. I am new in laravel and i don't know how to make my query into laravel query. Here is my query :
$date1 = date("Y-m-d", strtotime($request->datepicker));
$date2 = date("Y-m-d", strtotime($request->datepicker1));
$products = DB::table('shipping_table')
->select('products.product_name', 'products.price', DB::raw('Sum(shipping_products.quantity) AS qtysold'), 'shipping_table.sold_date')
->join('shipping_products','shipping_table.shipping_id', '=', 'shipping_products.shipping_id')
->join('products','products.product_id', '=', 'shipping_products.product_id')
->where(['shipping_table.shipping_status', '=' ,1])
->whereBetween(DB::raw("date(shipping_table.sold_date"),[$date1,$date2])
->groupBy('products.product_name')
->get();
please take a look in whereBetween because i am suspecting if it's the one who has wrong syntax.
Error:
Syntax error or access violation: 1064
Got it! You are missing an ) on your between clause:
$date1 = date("Y-m-d", strtotime($request->datepicker));
$date2 = date("Y-m-d", strtotime($request->datepicker1));
$products = DB::table('shipping_table')
->select('products.product_name', 'products.price', DB::raw('Sum(shipping_products.quantity) AS qtysold'), 'shipping_table.sold_date')
->join('shipping_products','shipping_table.shipping_id', '=', 'shipping_products.shipping_id')
->join('products','products.product_id', '=', 'shipping_products.product_id')
->where('shipping_table.shipping_status',1)
->whereBetween(DB::raw("date(shipping_table.sold_date)"),[$date1,$date2])
->groupBy('products.product_name')
->get();
Try now