Laravel Query Conversion Needed - mysql

I need to convert the following mysql query into laravel query builder :
SELECT id.product_id FROM
(
SELECT product_id, count(i.product_id) as t, c.filter_group as b
FROM
(
SELECT f.filter_id, f.product_id, p.filter_group_id
FROM ". DB_PREFIX ."product_filter f
left join ". DB_PREFIX ."filter p ON p.filter_id = f.filter_id
where p.filter_id IN
(1, 4, 5, 3)
GROUP BY product_id , filter_group_id
)
as i,
(
select count(distinct filter_group_id) as filter_group
from ". DB_PREFIX ."filter_description f_b
WHERE f_b.filter_id in (1, 4, 5, 3)
)
as c GROUP BY product_id HAVING t = b
)
as id
So Far, I have done :
$query = DB::select('id.product_id')
->fromSub(function ($query) {
$query->select('product_id', DB::raw('COUNT(i.product_id) AS t'), 'c.filter_set AS b')
->fromSub(function ($query) {
$query->select('f.filter_id', 'f.product_id', 'p.filter_set_id')
->from(config('db.tables.EcomRelationProductFilters').' AS f')
->leftJoin(config('db.tables.EcomFilters').' AS p', 'p.filter_id', '=', 'f.filter_id')
->whereIn('p.filter_id', $filter_ids)
->groupBy('product_id', 'filter_set_id');
}, 'i')
->fromSub(function ($query) {
$query->select(DB::raw('COUNT(distinct filter_set_id) AS filter_set'))
->from(config('db.tables.EcomFilterDetails').' AS f_b')
->whereIn('f_b.filter_id', $filter_ids);
}, 'c')
->groupBy('product_id')
->having('t', '=', 'b');
}, 'id')->toSql();
But I am having issues with this, It says there are syntax erros in my query.
Updated :
Exact error I am getting :
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 'id.product_id' at line 1 (SQL: id.product_id)

Related

issue in mysql query in codeigniter only if I add if condition

In below code, whenever I am adding below code with if conditions, i am getting error
if($this->ion_auth->is_customer())
$this->db->where('company_database.cdb_customer_id',$this->session->userdata('user_id'));
$this->db->select('company.*, cities.name as company_city, states.name as company_state, countries.name as company_country');
$this->db->from('company as company');
$this->db->join(CITIES.' as cities','cities.id = company.company_city_id' ,'left');
$this->db->join(STATES.' as states','states.id = company.company_state_id' ,'left');
$this->db->join(COUNTRIES.' as countries','countries.id = company.company_country_id' ,'left');
$this->db->join(COMPANY_DATABASE.' as company_database','company_database.cdb_company_id = company.company_id' ,'left');
if($this->ion_auth->is_customer())
$this->db->where('company_database.cdb_customer_id',$this->session->userdata('user_id'));
$this->db->where('company.company_delete_status',NOT_DELETED);
$query = $this->db->get();
echo '<pre>';
echo $this->db->get_compiled_query();
print_r($query->result());
echo $this->db->last_query();
What is the issue above query ?
I am getting below issue related to query
Error Number: 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 'WHERE `company_database`.`cdb_customer_id` = '19' AND `company`.`company_delete_' at line 2
SELECT * WHERE `company_database`.`cdb_customer_id` = '19' AND `company`.`company_delete_status` = 0
Filename: controllers/Test.php
Line Number: 112
You don't have a "from" clause in your where clause.
select * {from company} where 'company_database'.'cdb_customer_id' = ....
I suspect that the function
$this->ion_auth->is_customer()
may be calling another DB query and that pretty much completes the query you started above and once completed it does the $this->db with just the where clauses after.
To fix call the $this->ion_auth->is_customer() before you do $this->db->select and then in the IF statement simply just use the boolean returned so you don't
make another call to a query while you form another query.
Example:
--ADD THIS LINE
$bIsClient = $this->ion_auth->is_customer();
$this->db->select('company.*, cities.name as company_city, states.name as company_state, countries.name as company_country');
$this->db->from('company as company');
$this->db->join(CITIES.' as cities','cities.id = company.company_city_id' ,'left');
$this->db->join(STATES.' as states','states.id = company.company_state_id' ,'left');
$this->db->join(COUNTRIES.' as countries','countries.id = company.company_country_id' ,'left');
$this->db->join(COMPANY_DATABASE.' as company_database','company_database.cdb_company_id = company.company_id' ,'left');
--AND CHANGE THIS
if($bIsClient)
$this->db->where('company_database.cdb_customer_id',$this->session->userdata('user_id'));
$this->db->where('company.company_delete_status',NOT_DELETED);
$query = $this->db->get();
echo '<pre>';
echo $this->db->get_compiled_query();
print_r($query->result());
echo $this->db->last_query();

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;

Sql leftJoin query using laravel syntax showing error

This is my query that i used for left join, it is working fine but something is missing when I convert it to laravel syntax.
Query to convert is
$result = DB::select("select amenities.name as
name,amenities.type_id,amenities.id as id, amenities.icon, rooms.id as status
from amenities left join rooms on find_in_set(amenities.id, rooms.amenities)
and rooms.id = $room_id and type_id !=4");
and the I am doing this
$result = DB::table('amenities')
->select('amenities.name as name', 'amenities.type_id' , 'amenities.id as id'
, 'amenities.icon', 'rooms.id as status' )
->leftJoin('rooms', function ($join) {
$join->on('FIND_IN_SET(amenities.id, rooms.amenities)')
->where('rooms.id' , '=', '$room_id')
->where('type_id','!=', 4);
})->get();
The error is
InvalidArgumentException in
F:\xampp\htdocs\arheb\Arheb\vendor\laravel\framework\src\Illuminate\Database\Query\JoinClause.php
line 79: Not enough arguments for the on clause.
Your query is wrong. I assume that amenities.id and rooms.amenities are attributes of amenities and rooms table respectively.
MySQL FIND_IN_SET() returns the position of a string if it is present (as a substring) within a list of strings.
You need to pass column names in first and second parameter of on() function.
$result = DB::table('amenities')
->select('amenities.name as name', 'amenities.type_id' , 'amenities.id as id'
, 'amenities.icon', 'rooms.id as status' )
->leftJoin('rooms', function ($join) {
$join->on('amenities.id', '=', 'rooms.amenities')
->where('rooms.id' , '=', '$room_id')
->where('type_id','!=', 4);
})->get();
I think you can try this:
$result = DB::table('amenities')
->select('amenities.name as name', 'amenities.type_id' , 'amenities.id as id'
, 'amenities.icon', 'rooms.id as status' )
->leftJoin('rooms', function ($join) {
$join->on(DB::raw("find_in_set(amenities.id, rooms.amenities)"))
->where('rooms.id' , '=', '$room_id')
->where('type_id','!=', 4);
})->get();
Hope this work for you!

Laravel join tables and concatenate rows

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

MYSql - Using correlated subquery in Zend Db

I'm trying to construct a working MySql query with a correlated subquery in zend_db_select (ZF 1.12) to use that in Zend_Paginator_Adapter. The working query is as follows:
SELECT f.*, (SELECT (COUNT(p.post_id) - 1)
FROM `forum_topic_posts` AS p WHERE f.topic_id = p.topic_id) AS post_count
FROM `forum_topics` AS f WHERE f.forum_id = '2293'
ORDER BY post_count DESC, last_update DESC
So i worked out:
$subquery = $db->select()
->from(array('p' => 'forum_topic_posts'), 'COUNT(*)')
->where('p.topic_id = f.topic_id');
$this->sql = $db->select()
->from(array('f' => 'forum_topics'), array('*', $subquery . ' as post_count'))
->where('forum_id=?', $forumId, Zend_Db::PARAM_INT)
->order('post_count ' . $orderDirection);
But Zend stops with the following exception when executing the query:
Zend_Db_Statement_Mysqli_Exception: Mysqli prepare error: 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 'SELECT COUNT(*) FROM forum_topic_posts AS p WHERE (p.topic_id = f.to' at line 1
How could i get the subquery to work?
Here is the query written using the Zend_Db OO interface.
The key was mostly using some Zend_Db_Expr objects for the subquery and COUNT function.
$ss = $db->select()
->from(array('p' => 'forum_topic_posts'),
new Zend_Db_Expr('COUNT(p.post_id) - 1'))
->where('f.topic_id = p.topic_id');
$s = $db->select()
->from(array('f' => 'forum_topics'),
array('f.*', 'post_count' => new Zend_Db_Expr('(' . $ss . ')')))
->where('f.forum_id = ?', 2293)
->order('post_count DESC, last_update DESC');
echo $s;
// SELECT `f`.*, SELECT COUNT(p.post_id) - 1 FROM `forum_topic_posts` AS `p` WHERE (f.topic_id = p.topic_id) AS `post_count` FROM `forum_topics` AS `f` WHERE (f.forum_id = 2293) ORDER BY `post_count DESC, last_update` DESC