Join Statement using Query builder with multiple where clause - sql

I have a Query builder statement below and I would want to introduce another condition to the query. However, I can not get this right.
This query works fine;
$content = DB::table('subscribed_services as a')
->join('scheduled_messages as b', 'a.id', '=', 'b.subscribed_services_id')
->join('subscription_services_msisdn as c', 'a.id', '=', 'c.subscribed_services_id')
->whereRaw('DATE(b.scheduled_at) = CURDATE()')
->selectRaw('b.message, c. phone_number, a.username, a.password')
->distinct()
->get();
I would want to introduce another where statement; this ->whereRaw('DATE(c.sent_time) != CURDATE()'). Meaning the query above should only pick values where subscription_services_msisdn.sent_time DATE(c.sent_time) IS NOT EQUAL to Current Date CURDATE().
Anyone lead me here. Regards.

You can chain as many where conditions as you want, so just add another whereRaw to the chain:
$content = DB::table('subscribed_services as a')
->join('scheduled_messages as b', 'a.id', '=', 'b.subscribed_services_id')
->join('subscription_services_msisdn as c', 'a.id', '=', 'c.subscribed_services_id')
->whereRaw('DATE(b.scheduled_at) = CURDATE()')
->whereRaw('DATE(c.sent_time) <> CURDATE()')
->selectRaw('b.message, c. phone_number, a.username, a.password')
->distinct()
->get();

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();

How to get number of customer and total amount for time range?

I want to have the result of the table below, I have two tables, one for the clients and one for the transactions made by the clients.Someone can help me to achieve that!Thank's in advance
here is what i want to return
This the query i write to get the result.
$customers_trans = DB::table('contacts as c')
->select(
DB::raw('SUM(tr.final_total) AS total_customer'),
DB::raw('COUNT(c.id) AS customercount'),
DB::raw('COUNT(c.id) AS average')
)
->whereBetween('tr.transaction_date', [$date_debut, $date_fin])
->groupBy('c.id')
->join('transactions as tr', 'tr.contact_id', '=', 'c.id')
->get()->toArray();
I think this is what you want:
$customers_trans = DB::table('contacts as c')
->select(
DB::raw('SUM(tr.final_total) AS total_customer'),
DB::raw('COUNT(*) AS customer_count'),
DB::raw('AVG(tr.final_total) AS average')
)
->join('transactions as tr', 'tr.contact_id', '=', 'c.id')
->whereBetween('tr.transaction_date', [$date_debut, $date_fin])
->groupByRaw('HOUR(tr.transaction_date)')
->get()
->toArray();

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

Kohana ORM ordering

I'm using Kohana's ORM library, and I'm wondering if there is any way to select DB records in a particular predetermined sequence.
$products_ids = array('5', '6', '1', '33', '2');
$products = ORM::factory('Product')->where('state', '=', 1)
->and_where('id', 'IN', $products_ids)->find_all();
This orders result by primary key (id). So result records ordered like (1, 2, 5, 6, 33). How select records by order defined in $products_ids ('5', '6', '1', '33', '2')?
Thanks.
Yes this is possible.
$products = ORM::factory('Product')->where('state', '=', 1)
->and_where('id', 'IN', $products_ids)->order_by('product_id', 'desc')->find_all();
Note the added order_by() in the string above.
You can order your results now. It has more cool features like group_by().
Read the documentation and you will find more unexpected magic in ORM.
In MySQL you can have conditions in order by clause where if the condition match it gets treated as 1 and 0 on fails.
The code for the example would be:
$products_ids = array('5', '6', '1', '33', '2');
$products = ORM::factory('Product')->where('state', '=', 1)->and_where('id', 'IN', $products_ids);
foreach($products_ids as $product_id)
{
$products->order_by(DB::expr('id='.$product_id), 'desc');
}
$products = $products->find_all();
In MySQL it would look something like this:
SELECT * FROM products WHERE ... ORDER BY id=5 DESC, id=6 DESC, id=1 DESC, id=33 DESC, id=2 DESC;
I don't know why you wan do so stupid thing, but 2 answers you have. (For stric problem. But probably you don't show full background.
I propose 2 scenarios:
Products on page category - add column for order it to table.
Display shopping chart - order by order_item_id
BTW: ORM is comfortable, but slow, so if you nedd it only for display (read operation) better is using raw query. Here solution for ORM.
public function get_ordered(array $ids){
if(empty($ids))
return array();
$res = DB::select->from($this->_table_name)
->where($this->primary_key(),'IN',$ids)
->execute($this->_db)->as_array($this->primary_key());
$out = array();
foreach($ids AS $one){
if(isset($res[$one]))
$out[$one] = $res[$one];
}
return $out;
}

How would I write this SQL in DQL?

What I'm after is the following SQL query
SELECT p.*
FROM player p
WHERE CONCAT(p.first_name, ' ', p.last_name) = ?
in DQL. What I have so far is
$qb->add('select', 'p')
->add('from', 'VNNCoreBundle:Player p')
->add('where', $qb->expr()->eq(
$qb->expr()->concat('p.firstName', $qb->expr()->concat(' ', 'p.lastName')),
':name'
))
->setParameters(array('name' => $name));
but that's wrong.
I know I could always just get the ID of my record with native SQL, then do findOneById() to get the record with Doctrine. On one hand, it feels like a kludge/hack to do that, and on the other hand, it feels kind of dumb to do in DQL to do what would be a simple query in straight SQL, since the DQL isn't shaping up to be very elegant. Anyway, I've put this much time into it, and I'm curious now what the right way to do it is in DQL.
I ended up going the native SQL route. I kind of forgot about that third option.
$rsm = new ResultSetMapping;
$rsm->addEntityResult('Player', 'p');
$rsm->addFieldResult('p', 'id', 'player_id');
$rsm->addFieldResult('p', 'name', 'name');
$sql = "
SELECT p.*
FROM players p
WHERE CONCAT(p.first_name, ' ', p.last_name) = ?
";
$query = $this->getEntityManager()->createNativeQuery($sql, $rsm);
$query->setParameter(1, $name);