Laravel query builder left join from subquery - sql

I'm using Laravel query builder and trying to do something like this:
$builder = DB::table('mainTable')->where("mainTable.id", "=", 111);
$builder->leftJoinSub(
DB::table('table2')
->where('table2.id', '=', DB::raw("mainTable.subtableId"))
->where('table2.region', '=', DB::raw("mainTable.region"))
->orderBy('table2.someOrder', 'DESC')
->select('kamery2.id')
->first(),
'myId',
'table2.id',
'=',
'myId'
);
And I'm getting
The multi-part identifier "mainTable.subtableId" could not be bound.
However when I write it with DB::raw('...') it works.
$builder->leftJoin(
'table2',
'table2.id',
'=',
DB::Raw("...")
);
So I'm trying to find out what I'm doing wrong. Did I make a syntactic mistake only? Or Laravel query's builder doesn't allow what I want to achieve and I have to use ->leftJoin(.... DB::raw() ) ?

Related

exists query does not return relevant result

I have a Laravel application with this Eloquent query:
$products = Product::where('name', 'LIKE', "%{$value}%")
->whereHas('categories', function($q) {
$q->where( 'slug', 'tonery-cartridge' );
})->with('manufacturer')
->with('sm_image')
->orderBy('created_at','DESC')
->take(10)
->get();
This code generates the sql command like:
select * from `products` where `name` LIKE '%can%'
and exists (
select * from `categories` inner join `category_product`
on `categories`.`id` = `category_product`.`category_id`
where `products`.`id` = `category_product`.`product_id`
and `slug` = 'tonery-cartridge'
)
order by `created_at` desc limit 10
I am sure there are products which name contains "can" string and which belongs to the category with slug "tonery-cartridge". Why this query returns an empty result? If I try to make inner join sql manually it works well as on the screenshot below:
I think that your queries are not equivalent. The SQL output from laravel does not join tables in it's FROM clause, but in your manually constructed SQL statement you do a lot of inner joins in your FROM clause and on the resulting table you perform your operations, which is not true for the former.
Try the following
DB::table('products')
->join('category_product', 'category_product.product_id', '=', 'products.id')
->join('categories', 'category_product.category_id', '=', 'categories.id')
->whereRaw('products.name LIKE %can% AND categories.slug = "tonery-cartridge"')
->select('products.name', 'categories.slug')
->orderBy('created_at','DESC')
->take(10)
->get()
If you want to avoid using whereRaw, you can try the following.
DB::table('products')
->join('category_product', 'category_product.product_id', '=', 'products.id')
->join('categories', 'category_product.category_id', '=', 'categories.id')
->where([
['products.name, 'LIKE', '%' . $value . '%'],
['categories.slug', '=', 'tonery-cartridge']])
->select('products.name', 'categories.slug')
->orderBy('created_at','DESC')
->take(10)
->get()
HTH
This could be one of the solutions
$category = Category::where( 'slug', 'tonery-cartridge' )->first();
$products = $category->products()
->where('name', 'LIKE', "%{$value}%")
->with('manufacturer')
->with('sm_image')
->latest()
->take(10)
->get();

fetch data using query builder by checking multiple data from same column in laravel

DB::table('products')
->where('status', '=', 'published')
->where('sub_category', '=', 'grooming-wellness')
->where('sub_category', '=', 'beauty-care')
->get();
it doesn't work. it returns 0 data.
I am assuming you want to check if a field has a particular value or another value. You can use whereIn to achieve this:
DB::table('products')
->where('status', '=', 'published')
->whereIn('sub_category', ['grooming-wellness', 'beauty-care'])
->get();
Laravel 6.x Docs - Query Builder - Where Clauses - Additional Where Clauses whereIn

Laravel Query Builder Statement return no result, but sql statement does

Laravel Query Builder
$data = CustomerPrepaid
::join('pos_sales', 'customer_prepaid.customer_id', '=', 'pos_sales.customer_id')
->join('pos_sales_product', 'pos_sales.pos_sales_code', '=', 'pos_sales_product.pos_sales_code')
->where('pos_sales_product.product_id', 'customer_prepaid.product_id')
->select('customer_prepaid.customer_id', 'customer_prepaid.created_at',
'pos_sales_product.pos_sales_product_code as reference_no',
'customer_prepaid.product_id', 'customer_prepaid.balance',
'last_used', 'expiry_date', 'customer_prepaid.amount as price')
->offset(($page-1)*$limit)->limit($limit)->get();
SQL
SELECT customer_prepaid.customer_id, customer_prepaid.created_at as purchase_date,
pos_sales_product.pos_sales_product_code as reference_no, customer_prepaid.product_id,
customer_prepaid.balance, customer_prepaid.amount*customer_prepaid.balance as value,
last_used, expiry_date, customer_prepaid.amount as price,
customer_prepaid.amount*customer_prepaid.balance as total
FROM customer_prepaid
JOIN pos_sales ON customer_prepaid.customer_id = pos_sales.customer_id
JOIN pos_sales_product ON pos_sales.pos_sales_code = pos_sales_product.pos_sales_code
WHERE pos_sales_product.product_id = customer_prepaid.product_id
The resulting SQL executed on the server returns the right result, but I get no eloquent result, why might that be?
Oh gosh, took me forever to realize you misused ->where.
Change your ->where to ->whereColumn:
$data = CustomerPrepaid
::join('pos_sales', 'customer_prepaid.customer_id', '=', 'pos_sales.customer_id')
->join('pos_sales_product', 'pos_sales.pos_sales_code', '=', 'pos_sales_product.pos_sales_code')
->whereColumn('pos_sales_product.product_id', 'customer_prepaid.product_id')
->select(
'customer_prepaid.customer_id',
'customer_prepaid.created_at',
'pos_sales_product.pos_sales_product_code as reference_no',
'customer_prepaid.product_id', 'customer_prepaid.balance',
'last_used', 'expiry_date', 'customer_prepaid.amount as price'
)
->offset(($page-1)*$limit)
->limit($limit)
->get();
You have to use whereColumn instead of where to make column comparison. Else it's expecting a third parameter value to be set.
Check the documentation on how to use whereColumn: https://laravel.com/docs/5.5/queries#where-clauses

Column not found in laravel

I'm trying to create a self join in laravel using aliases, but it doesn't seem to want to pick it up, because I get an error saying that the columns p1.sub_menu and p2.5 are not found. Here is my join:
$menu = DB::table('pages AS p1')
->leftJoin('pages AS p2', 'p1.sub_menu', '=', 'p2.'.$id.'')->get();
Error because of your leftJoin statement
Params in leftJoin statement are columns which you want to use relationships.
$menu = DB::table('pages AS p1')->leftJoin('pages AS p2', 'p1.sub_menu', '=', **'p2.'.$id.''**)->get();
My solution is:
$menu = DB::table('pages AS p1')->leftJoin('pages AS p2', 'p1.sub_menu', '=', 'p2.sub_menu')->where("p2.menu_id", "=", $menu_id)->get();

Translating SQL query to Doctrine2 DQL

I'm trying to translate this (My)SQL to DQL
SELECT content, created, AVG(rating)
FROM point
GROUP BY DAY(created)
ORDER BY created ASC
And I'm stuck at GROUP BY part, apparently DAY/WEEK/MONTH isn't recognized as valid "function".
[Semantical Error] line 0, col 80 near '(p.created) ORDER': Error: Cannot group by undefined identification variable.
$this->createQueryBuilder('p')
->select('p')
->groupBy('DAY(p.created)')
->orderBy('p.created', 'ASC')
Q: Is it possible to create this kind of query with query builder, or should I use native query?
It is not possible to use custom DAY/WEEK/MONTH user functions in GROUP BY queries in Doctrine 2.1.?, only SELECT queries are supported (not sure for 2.2.? branch), so I ended up using native query, and everything works fine.
Quick overview of the code:
// creating doctrines result set mapping obj.
$rsm = new Doctrine\ORM\Query\ResultSetMapping();
// mapping results to the message entity
$rsm->addEntityResult('Omglol\AppBundle\Entity\Message', 'm');
$rsm->addFieldResult('m', 'id', 'id');
$rsm->addFieldResult('m', 'content', 'content');
$rsm->addFieldResult('m', 'rating', 'rating');
$rsm->addFieldResult('m', 'created', 'created');
$sql = "SELECT id, content, AVG(rating) as rating, created
FROM message
WHERE domain_id = ?
GROUP BY WEEK(created)";
$query = $this->_em->createNativeQuery($sql, $rsm);
$query->setParameter(1, $domainId);
$query->getResult();
There is the same topic in :
Link to google group