How to use WITH clause in Laravel Query Builder - laravel

I have SQL query (see example).
But I can't find a way how I can write it in Query Builder.
Do you have any ideas how is it possible?
WITH main AS (
SELECT id FROM table1
)
SELECT * FROM table2
WHERE
table2.id IN (SELECT * FROM main)
I want to get format like:
$latestPosts = DB::table('posts')
->select('user_id', DB::raw('MAX(created_at) as last_post_created_at'))
->where('is_published', true)
->groupBy('user_id');
$users = DB::table('users')
->joinSub($latestPosts, 'latest_posts', function ($join) {
$join->on('users.id', '=', 'latest_posts.user_id');
})->get();
but for WITH

Laravel has no native support for common table expressions.
I've created a package for it: https://github.com/staudenmeir/laravel-cte
You can use it like this:
$query = DB::table('table1')->select('id');
$result = DB::table('table2')
->withExpression('main', $query)
->whereIn('table2.id', DB::table('main')->select('id'))
->get();

Query builder has to be compatible with multiple database engines (mysql, postgresql, sql lite, sql server) and as such only offers support for common functionality.
Assuming your query returns data, you may be able to use the DB:select() method to execute a raw query.
$data = DB::select('WITH main AS (SELECT id FROM table1), SELECT * FROM table2 WHERE table2.id IN (SELECT * FROM main)');
The DB:select method also accepts a second parameter for using named bindings.
Alternatively there are packages available such as laravel-cte that will add the functionality to Eloquent/ Query Builder.

Related

GraphQL Where Select Sub Query

These day, i have studied GraphQL with Laravel framework, Lighthouse Library.
I have tried to do kind of SELECT Query.
As a result, I wonder GraphQL can select below SQL Query
SELECT * FROM TABLE_A WHERE type=1 AND chart_id=(SELECT id FROM TABLE_B WHERE phone='0000~~')
I expect, Client first get result from this query.
SELECT id FROM TABLE_B WHERE phone='0000~~'
And then Do Second query, i think i can get a result.
But i wonder I can get result from 1 request. Thanks.
You can try following
$phoneNumber = '0000~~';
$data = DB::table('tableA')->where('type',1)
->whereIn('chart_id',function($query) use ($phoneNumber) {
$query->select('id')
->from('tableB')
->where('phone', '=',$phoneNumber);
})->get();
If there is relationship between tableA and tableB you can do following
TableA::where('type',1)
->whereHas('tableBRelationshipName', function ($q) use ($phoneNumber) {
$q->select('id')
$q->where('phone','=',$phoneNumber);
})->get();

Complex SQL Query laravel Build

How would I use query builder in Laravel to generate the following SQL statement:
SELECT MAX(QTE) FROM (SELECT SUM(activity_sale_report.quantity_sold)
AS QTE FROM activity_sale_report
GROUP BY activity_sale_report.activity_id) AS T
If you are just using the query builder and not models you can use raw queries
$query = DB::select( DB::raw("SELECT MAX(QTE) FROM (SELECT SUM(activity_sale_report.quantity_sold) AS QTE FROM activity_sale_report GROUP BY activity_sale_report.activity_id) AS T);
I would recommend using the eloquent models, it's easier.

Converting a raw query to Laravel query builder

I have the following MySQL query which fetches a list of the last 9 authors to write a post and lists them in order of the date of the last post they wrote.
It's working properly but I'd like to re-write it using the Laravel Query Builder. Here is the query at the moment:
$authors = DB::select("
SELECT
`a`.`id`,
`a`.`name`,
`a`.`avatar`,
`a`.`slug` AS `author_slug`,
`p`.`subheading`,
`p`.`title`,
`p`.`slug` AS `post_slug`,
`p`.`summary`,
`p`.`published_at`
FROM
`authors` AS `a`
JOIN
`posts` AS `p`
ON `p`.`id` =
(
SELECT `p2`.`id`
FROM `posts` AS `p2`
WHERE `p2`.`author_id` = `a`.`id`
ORDER BY `p2`.`published_at` DESC
LIMIT 1
)
WHERE
`a`.`online` = 1
ORDER BY
`published_at` DESC
LIMIT 9
");
I understand the basics of using the query builder, but there doesn't appear to be anything in the Laravel docs that allows for me to JOIN a table ON a SELECT.
Can anyone suggest a way that I can write this query using the Laravel Query builder, or perhaps suggest a way that I can rewrite this query to make it easier to structure with the query builder?
Try to do like this
$data = DB::table('authors')
->select(
'a.id',
'a.name',
'a.avatar',
'a.slug AS author_slug',
'p.subheading',
'p.title',
'p.slug AS post_slug',
'p.summary',
p.published_at')
->from('authors AS a')
->join('posts AS p', 'p.id', '=', DB::raw("
(
SELECT p2.id FROM posts AS p2
WHERE p2.author_id = b.id
ORDER BY p2.published_at
DESC LIMIT 1
)"))
->where('a.online', 1)
->limit(9)
->orderBy('p.published_at', 'desc')
->get();

Need to convert raw sql to eloquent query builder

I need to convert the following sql query to eloquent query builder.
select * from projects
inner join assigned_projects on projects.id = assigned_projects.project_id
where assigned_projects.user_id=9;
where projects and assigned_projects are in many to many relation. Please help me figure it out.
$project = DB::table('projects')
->join('assigned_projects' , 'projects.id' , '=', 'assigned_projects.project_id')
->where('assigned_projects.user_id', '=', 9)
->get();

Using Mysql WHERE IN clause in codeigniter

I have the following mysql query. Could you please tell me how to write the same query in Codeigniter's way ?
SELECT * FROM myTable
WHERE trans_id IN ( SELECT trans_id FROM myTable WHERE code='B')
AND code!='B'
You can use sub query way of codeigniter to do this for this purpose you will have to hack codeigniter. like this
Go to system/database/DB_active_rec.php
Remove public or protected keyword from these functions
public function _compile_select($select_override = FALSE)
public function _reset_select()
Now subquery writing in available
And now here is your query with active record
$this->db->select('trans_id');
$this->db->from('myTable');
$this->db->where('code','B');
$subQuery = $this->db->_compile_select();
$this->db->_reset_select();
// And now your main query
$this->db->select("*");
$this->db->where_in("$subQuery");
$this->db->where('code !=', 'B');
$this->db->get('myTable');
And the thing is done. Cheers!!!
Note : While using sub queries you must use
$this->db->from('myTable')
instead of
$this->db->get('myTable')
which runs the query.
Watch this too
How can I rewrite this SQL into CodeIgniter's Active Records?
Note : In Codeigntier 3 these functions are already public so you do not need to hack them.
$data = $this->db->get_where('columnname',array('code' => 'B'));
$this->db->where_in('columnname',$data);
$this->db->where('code !=','B');
$query = $this->db->get();
return $query->result_array();
Try this one:
$this->db->select("*");
$this->db->where_in("(SELECT trans_id FROM myTable WHERE code = 'B')");
$this->db->where('code !=', 'B');
$this->db->get('myTable');
Note: $this->db->select("*"); is optional when you are selecting all columns from table
try this:
return $this->db->query("
SELECT * FROM myTable
WHERE trans_id IN ( SELECT trans_id FROM myTable WHERE code='B')
AND code!='B'
")->result_array();
Is not active record but is codeigniter's way http://codeigniter.com/user_guide/database/examples.html
see Standard Query With Multiple Results (Array Version) section
you can use a simpler approach, while still using active record
$this->db->select("a.trans_id ,a.number, a.name, a.phone")
$this->db->from("Name_Of_Your_Table a");
$subQueryIn = "SELECT trans_id FROM Another_Table";
$this->db->where("a.trans_id in ($subQueryIn)",NULL);

Resources