I want to convert my raw query to query builder - laravel

I m new in laravel
Actually I have a auth table which is link to the other table based on the user type. I want user info from corresponding tables so i use raw query now i want to convert it into query builder, Please help
$data = DB::select("SELECT srr.id,srr.created_at,srr.fromid,srr.toid,srr.from_usertype,au.firstname_admin,au.lastname_admin,cd.name as to_compayname,COALESCE(unionSub1.firstname,NULL) as from_firstname, unionSub1.lastname as from_lastname
from service_request_reviews as srr
left join (
(select authid, firstname, lastname from userdetails)
union (select authid, firstname, lastname from yachtdetail)
union (select authid, firstname, lastname from talentdetails)
union (select authid, name as firstname, COALESCE(NULL,NULL) as lastname from companydetails)
) unionSub1 on unionSub1.authid = srr.fromid
left join auths as au on au.id = srr.fromid
LEFT JOIN companydetails as cd ON cd.authid = srr.toid WHERE srr.isdeleted = '0' AND srr.parent_id1 = '0' " );
I have tried this and its working fine without union. I don't know how to use multiple unions inside left join.
$data = DB::table('service_request_reviews as srr')
->select('srr.id','srr.created_at','srr.fromid','srr.toid','srr.from_usertype','au.firstname_admin','au.lastname_admin','cd.name as to_compayname')
->leftjoin('auths as au', 'au.id', '=' ,'srr.fromid')
->leftjoin('companydetails as cd', 'cd.authid', '=', 'srr.toid')
->where('srr.isdeleted', '0')
->where('srr.parent_id', '0');

You can define union as query builder for that table Like:
$yachtdetail = DB::table("yachtdetail")
->select('authid', 'firstname', 'lastname');
$talentdetails = DB::table('talentdetails')
->select('authid', 'firstname', 'lastname');
Now you can use like:
$data = DB::table('service_request_reviews as srr')
->select('srr.id','srr.created_at','srr.fromid','srr.toid','srr.from_usertype','au.firstname_admin','au.lastname_admin','cd.name as to_compayname')
->leftjoin('auths as au', 'au.id', '=' ,'srr.fromid')
->leftjoin('companydetails as cd', 'cd.authid', '=', 'srr.toid')
->where('srr.isdeleted', '0')
->where('srr.parent_id', '0')
->union($yachtdetail)
->union($talentdetails)
->get();
Here is the link for the documentation. https://laravel.com/docs/5.8/queries#unions
Edited:
In your case you can try something like this:
$queryBuilder = DB::table('service_request_reviews as srr')
->select('srr.id','srr.created_at','srr.fromid','srr.toid','srr.from_usertype','au.firstname_admin','au.lastname_admin','cd.name as to_compayname')
->leftjoin('auths as au', 'au.id', '=' ,'srr.fromid')
->leftjoin('companydetails as cd', 'cd.authid', '=', 'srr.toid')
->leftjoin(DB::raw("((select authid, firstname, lastname from userdetails)
union (select authid, firstname, lastname from yachtdetail)
union (select authid, firstname, lastname from talentdetails)
union (select authid, name as firstname, null as lastname from companydetails)) as unionSub1"), function($join){
$join->on(DB::raw('unionSub1.authid'), '=', DB::raw('srr.fromid'));
})
->where('srr.isdeleted', '0')
->where('srr.parent_id', '0');
$data = $queryBuilder->get();

Related

Query a table with info from another one in Eloquent

I have two tables: Invoices and Clients. Each invoice have a client and each client has an expiration time for their invoices.
I want to get each invoice where the invoice date + the expiration time has passed current date.
I actualy did it with DB::select like this.
DB::select('SELECT DISTINCT i.id,(i.invoice_date+INTERVAL \'1 day\' * invoice_expiration) as expiration_date, i.invoice_date, c.invoice_expiration, c.id as client_id, c.name, i.total, i.status, c.rut FROM invoices i, clients c, invoice_cargos ic, cargos ca WHERE i.invoice_date+INTERVAL \'1 day\' * invoice_expiration < current_date AND i.client_id = c.id AND i.status not in (\'PAID\') and i.id = ic.invoice_id and ic.cargo_id = ca."id" AND i.iva = true AND ca.stage = \'APPROVED\' order by c.name, i.invoice_date ;');
But I'm having trouble translating that to eloquent.
The Invoice model has the relationship to the Client one:
Invoice Model:
public function client()
{
return $this->hasOne(Client::class,'id', 'client_id');
}
Laravel tries to guess, by conventions, the names of the columns in the relationships. I don't think id should be there as the second parameter. Also, you can omit client_id it would be easy for Laravel to guess that relationship, so, I'd leave it like this:
public function client()
{
return $this->hasOne(Client::class);
}
Something like this should work:
Invoice::select(DB::raw('DISTINCT i.id, (i.invoice_date + INTERVAL "1 day" * invoice_expiration) as expiration_date, i.invoice_date, c.invoice_expiration, c.id as client_id, c.name, i.total, i.status, c.rut'))
->join('clients as c', 'i.client_id', '=', 'c.id')
->join('invoice_cargos as ic', 'i.id', '=', 'ic.invoice_id')
->join('cargos as ca', 'ic.cargo_id', '=', 'ca.id')
->whereRaw('i.invoice_date + INTERVAL "1 day" * invoice_expiration < current_date')
->whereNotIn('i.status', ['PAID'])
->where('i.iva', true)
->where('ca.stage', 'APPROVED')
->orderBy('c.name')
->orderBy('i.invoice_date')
->get();
Alternatively, you can create columns in the database to store the calculated values so that you don't have to use raw SQL in your Eloquent query. For example, you could add a expiration_date column to the invoices table and update it with the calculated value when creating or updating an invoice. This would allow you to use a simple Eloquent query like this:
Invoice::where('expiration_date', '<', Carbon::now())
->whereNotIn('status', ['PAID'])
->where('iva', true)
->join('invoice_cargos as ic', 'invoices.id', '=', 'ic.invoice_id')
->join('cargos as ca', 'ic.cargo_id', '=', 'ca.id')
->where('ca.stage', 'APPROVED')
->orderBy('clients.name')
->orderBy('invoices.invoice_date')
->get();

laravel eloquent with and join conflict

I am quite new to Laravel... I have a posts table that has a relation with articles and users tables. In the controller I either get all the posts matching a search criteria or get all posts. In both cases, I learned how to add the related fields to the collection $posts.
// get all posts matching criteria
if (request('search') && request('search') != '') {
$posts = Post::orderBy($orderBySortField,$sortOrder)
->with(['user:id,name','article:id,title'])
->where('post','like','%'.request('search').'%')
->join('users', 'posts.user_id', '=', 'users.id')
->orWhere('users.name','like','%'.request('search').'%')
->join('articles', 'posts.article_id', '=', 'articles.id')
->orWhere('articles.title','like','%'.request('search').'%')
->get();
// get all posts
} else {
$posts = Post::orderBy($orderBySortField,$sortOrder)
->with(['user:id,name','article:id,title'])
->get();
}
// add related fields
foreach ($posts as $post) {
$post->title = '['.$post->article->title.']';
$post->user = '['.$post->user->name.']';
}
When I get all the posts, the related fields are correct in the list displayed in the view page.
However, if I search for the name of a specific user, I get a list where the $posts->user are incorrectly related.
I could figured that by displaying the last queries.
For all the posts:
select * from `posts` order by `posts`.`id` desc
select `id`, `name` from `users` where `users`.`id` in (1, 11)
select `id`, `title` from `articles` where `articles`.`id` in (1)
For the posts written by user 'paul' (user_id = 1):
select * from `posts` inner join `users` on `posts`.`user_id` = `users`.`id` inner join `articles` on `posts`.`article_id` = `articles`.`id` where `post` like ? or `users`.`name` like ? or `articles`.`title` like ? order by `posts`.`id` desc [where ? = %paul% %paul% %paul% ]
select `id`, `name` from `users` where `users`.`id` in (11)
select `id`, `title` from `articles` where `articles`.`id` in (1)
So why is Laravel last queries look for user_id = 11 which is another user?
Am I doing something wrong?
Change the join code the whereHas
// get all posts matching criteria
if (request('search') && request('search') != '') {
$search = request('search');
$posts = Post::orderBy($orderBySortField,$sortOrder)
->with(['user:id,name','article:id,title'])
->where('post','like','%'.$search.'%')
->orWhereHas('user', function($userQuery) use($search){
$userQuery->Where('users.name','like','%'.$search.'%');
})
->orWhereHas('article', function($articleQuery) use($search){
$articleQuery->Where('articles.title','like','%'.$search.'%');
})
->get();
}
If you have define model relation, you don't have to use join in your query, just use with function.
Using the two create duplicate data, that why you getting incorrectly related error.

convert mysql query to laravel builder 4.2

SELECT user_id, email, username, password, COUNT(*) AS count
FROM users
where email = 'dyz#dss.com'
GROUP BY password HAVING count > 0
ORDER BY count DESC;
I tried with below code does not work Please guide how to do this thanks in advance
User::SELECT('user_id, email, username, password, COUNT(*) AS count')
->where('email', Input::get('username'))
->groupBy('password')
->havingRaw('count > 0')
->orderBy('count', 'DESC')
->get();
You should try this
DB::table('users')
->select(DB::raw('count(*) as count, user_id, email, username, password'))
->where('email', Input::get('username'))
->orderBy('count', 'DESC')
->groupBy('password')
->having('count', '>', 0)
->get();

codeigniter active record get last 10 records and sort ASC

I would like to know if this SQL statement is done in Codeigniter active record.
SELECT * FROM (
SELECT *
FROM chat
WHERE (userID = $session AND toID = $friendID)
OR (userID = $friendID AND toID = $session)
ORDER BY id DESC
LIMIT 10
) AS `table` ORDER by id ASC
You have to use the _compile_select() and _reset_select() methods of the active record class.
$this->db->select('*');
$this->db->from('chat');
$this->db->where("(userID='{$session}' AND toID='{$friendID}')");
$this->db->or_where("(userID='{$friendID}' AND toID='{$session}')");
$this->db->order_by('id', 'DESC');
$this->db->limit('10');
$subQuery = $this->db->_compile_select();
$this->db->_reset_select();
$this->db->select('*');
$this->db->from("{$subQuery} AS table");
$this->db->order_by('id', 'ASC');
$query = $this->db->get();
Unfortunately, in CI 2.0+, _compile_select() and _reset_select() are protected methods. Bummer. You'll have to follow this tutorial on extending the DB driver where you can write methods like the following:
function get_compiled_select()
{
return $this->db->_compile_select();
}
function do_reset_select()
{
$this->db->_reset_select();
}
I would like to take the time to point out that this type of action would be better served by joins. You should consider changing your db structure so that joins are possible and efficient.
This will work, though is not the active record variant.
$this->db->query( "SELECT * FROM (
SELECT *
FROM chat
WHERE (userID = ? AND toID = ?)
OR (userID = ? AND toID = ?)
ORDER BY id DESC
LIMIT 10
) AS `table` ORDER by id ASC", array( $session, $friendID, $friendID, $session) );"
You can use query as:
$this->db->select('SELECT *
FROM chat
WHERE (userID = $session AND toID = $friendID)
OR (userID = $friendID AND toID = $session)
ORDER BY id DESC
LIMIT 10') AS `table` ORDER by id ASC', FALSE);

Query Builder / DQL not working with INNER JOIN - Syntax Issue

I know I have a syntax isse here however I cant figure it out. I'm trying to do a SELECT and INNER JOIN of 5 tables but Symfony is complaining about the Entities in the JOIN are used before being defined.
Actual error is as follows: [Semantical Error] line 0, col 121 near 'I ON C.id = ': Error: Identification Variable MySiteBundle:Items used in join path expression but was not defined before.
Here is the PHP code.
Note: I have shortened this query to two columns, two tables, and one join to keep the question simple and show my point. The actual query is much longer and is producing the same error.
$em = $this->getDoctrine()->getEntityManager();
$query = $em->createQuery(
'select C.name as CName, I.id as IId
FROM MySiteBundle:Categories C
INNER JOIN MySiteBundle:Items I ON C.id = I.category_id');
$result = $query->getResult();
Update
As suggested I've done away with the DQL code and am using Query Builder code. I'm getting a very similiar error which says 'Categories c': Error: Class 'Categories' is not defined. My QB code is below.
$em = $this->getDoctrine()->getEntityManager();
$qb = $em->createQueryBuilder()
->select('c.name, i.id, i.image, i.name, i.description, m.id, m.quantity, m.value, m.qty_received, m.custom_image, m.custom_name, m.custom_description, u.user1fname, u.user1lname, u.user2fname, u.user2lname')
->from('Categories', 'c')
->innerJoin('Items', 'i', 'ON', 'c.id = i.category_id')
->innerJoin('MemberItems', 'm', 'ON', 'i.id = m.item_id')
->innerJoin('User', 'u', 'ON', 'm.memberinfo_id = u.id')
->where('u.id = ?', $slug)
->orderBy('c.id', 'ASC')
->getQuery();
$memberItems = $qb->getResult();
Any suggestions?
Louis posted while I was typing. Oh well.
DQL takes care of the join details for you based on your associations. In general, you only need to spell out the FROM class name. Something like:
'select C.name as CName, I.id as IId
FROM MySiteBundle:Categories C
INNER JOIN C.items');
And definitively use query builder.
=============================================================================
Here is an example of using query builder in Symfony 2.
public function getAccounts($params = array())
{
// Build query
$em = $this->getEntityManager();
$qb = $em->createQueryBuilder();
$qb->addSelect('account');
$qb->addSelect('accountPerson');
$qb->addSelect('person');
$qb->addSelect('registeredPerson');
$qb->addSelect('projectPerson');
$qb->from('ZaysoCoreBundle:Account','account');
$qb->leftJoin('account.accountPersons', 'accountPerson');
$qb->leftJoin('accountPerson.person', 'person');
$qb->leftJoin('person.registeredPersons','registeredPerson');
$qb->leftJoin('person.projects', 'projectPerson');
$qb->leftJoin('projectPerson.project', 'project');
if (isset($params['accountId']))
{
$qb->andWhere($qb->expr()->in('account.id',$params['accountId']));
}
if (isset($params['projectId']))
{
$qb->andWhere($qb->expr()->in('project.id',$params['projectId']));
}
if (isset($params['aysoid']))
{
$qb->andWhere($qb->expr()->eq('registeredPerson.regKey',$qb->expr()->literal($params['aysoid'])));
}
$query = $qb->getQuery();
//die('DQL ' . $query->getSQL());
return $query->getResult();
}
DQL does not use joins like that. They are a bit simplified. However I also found them to be underdocumented.
$em = $this->getDoctrine()->getEntityManager();
$query = $em->createQuery(
'select C.name as CName, I.id as IId
FROM MySiteBundle:Categories C
INNER JOIN C.items I');
$result = $query->getResult();
The actual relation used depends on your model.
I normally use the query builder.
$em = $this->getEntityManager();
$request = $em->getRepository('MySiteBundle:Categories');
$qb = $request->createQueryBuilder('C');
$query = $qb
->select('C.name, I.id')
->innerJoin('C.items', 'I')
->getQuery();
You may have to check your annotations or yml file to make sure you have your mapping setup correctly for OneToMany, ManyToMany, and ManyToOne.
In your MemberItems Controller or MemberItems Repository put this:
$em = $this->getDoctrine()->getEntityManager();
$qb = $em->createQueryBuilder()
->select('c.name, i.id, i.image, i.name, i.description, m.id, m.quantity, m.value, m.qty_received, m.custom_image, m.custom_name, m.custom_description, u.user1fname, u.user1lname, u.user2fname, u.user2lname')
->from('m')
->innerJoin('m.memberinfo_id', 'u')
->innerJoin('m.item_id', 'i')
->innerJoin('i.category_id', 'c')
->where(
->where('u.id = ?', $slug)
->orderBy('c.id', 'ASC')
->getQuery();
$memberItems = $qb->getResult();

Resources