Empty where clause in Laravel 5.1 preferring eloquent method - php

i am looking to produce the following query in laravel 5.1 with eloquent method.
The mysql query is a follows
SELECT * FROM orders WHERE 1 = 1 ORDER BY o_date DESC LIMIT 25
No matter what i cant get the
WHERE 1 = 1
part working.
am new to laravel and pretty sure this is easy. but can't figure it out.
I have tried the following variations
$orders = orders::where('1', 1)->orderBy('o_date', 'desc')->take(25)->get();
$orders = orders::where(1)->orderBy('o_date', 'desc')->take(25)->get();
$orders = orders::where('1', '=', '1')->orderBy('o_date', 'desc')->take(25)->get();
but its not working. the query results is as shown below
> select count(*) as aggregate from `orders`

Seems like (looking at 1=1) you need whereRaw
$orders = orders::whereRaw("any clause u wish")->orderBy('o_date', 'desc')->take(25)->get();
but if "any clause u wish" is not a VERY-VERY dinamical part u'd better look what else you can use
http://laravel.com/api/5.0/Illuminate/Database/Query/Builder.html
For the above example the below code works fine
$orders = orders::whereRaw("1 = 1")->orderBy('o_date', 'desc')->take(25)->get();

Why do you want to create a condition that will be always true? I think that Eloquent is smart enought to remove this useless part of the query.

Related

Laravel 5.6 groupBy on collection doesn't work

GroupBy just doesn't work on collection in Laravel 5.6, it is very annoying when simple things which supposed to work not wirking...
$users = Game::orderBy('game_count', 'desc')->get();
$users_grouped = $users->groupBy('user_id');
As you might guess $users_grouped contains the same collection as $users with the same repeating user_id values.
I don't get why it doesn't work as expected and how to fix it?
At least GROUP BY works with raw DB select hopefully.. But I want to use Eloquent..
You're confusing eloquent's query builder with collections. They are not the same thing.
groupBy on a query builder instance will use an SQL GROUP BY and give one aggregated result for the column(s) you are grouping on.
groupBy on a collection instance will return a new collection that groups all collected items by the given key's value.
https://laravel.com/docs/5.6/collections#method-groupby
If you want to use the query builder's groupBy method, chain it before the get():
$users = Game::orderBy('game_count', 'desc')->groupBy('user_id')->get();
get() executes the query and returns the collection of records.
If you want to group the query by user_id just do the groupBy before the get(), as the following row:
$users = Game::orderBy('game_count', 'desc')->groupBy('user_id')->get();
The rows will be the same. You should make two querys:
$users = Game::orderBy('game_count', 'desc')->get();
$users_grouped = Game::orderBy('game_count', 'desc')->groupBy('user_id')->get();
Temporary solution for this is the raw SQL query:
$users_grouped = DB::select('SELECT COUNT(id) AS theCount, `user_id` from `quiz_games` GROUP BY `user_id` ORDER BY theCount DESC');

What is meant by whereRaw in PHP Laravel framework

I'm unsure what whereRaw is in PHP Laravel framework. Could you provide good and easily understandable example, please?
WhereRaw() is a function of Laravel query builder which puts your input as it is in the SQL query's where clause.
Think of it as the where() function whose input argument will not be processed before inserting into queries.
See the example below:
$Query = DB::table('some_table')->where('YEAR(date)', 'YEAR(CURRENT_DATE)');
In this Laravel will resolve your arguments to build a query. Which will result in the following query because your input will be treated as some field and its its value :
SELECT * FROM `some_table` WHERE `YEAR(date)` = `YEAR(CURRENT_DATE)`
Which is not desired.
And now if you use whereRaw like:
$Query = DB::table('some_table')->whereRaw('YEAR(date) = YEAR(CURRENT_DATE)');
Now Laravel put this where clause as it is in your query, like below:
SELECT * FROM `some_table` WHERE YEAR(date) = YEAR(CURRENT_DATE)
Hope it helped (:
WhereRaw: Sometimes you may need to use a raw expression in a query. These expressions will be injected into the query as strings.
If you are unable to generate the query you need via the fluent interface, feel free to use whereRaw()
Ex:
$users = User::whereRaw('age > ? and votes = 100', array(25))->get();
which is equals to:
"SELECT * FROM users WHERE age > 25 AND votes = 100";
Reference
In laraval we use query builder. But Sometime you need to execute raw sql query.
So you can inject it to whereRaw as this example :
whereRAW('YEAR(event_datetime) =?', [$year])

laravel query builder

I want to write sql query
SELECT
*,
SUM(item_quantity)
FROM sales
GROUP BY item_id
ORDER BY SUM(item_quantity) DESC LIMIT 5
On laravel query builder but failed.
Can anyone please help me.
I use Model() instead of DB.
I think you are looking the following solution:
$sales = Sales::select('*', 'SUM(item_quantity) as total_item_qnty')
->groupBy('item_id')
->orderBy('total_item_qnty', 'desc')
->take(5)
Try this code

Yii2 - left join on multiple condition

I have three tables with the following relations,
------- 1 0..* ------------
|Product|-------------|Availability|
------- ------------
1 |
|
1 |
--------
|MetaData|
--------
my raw sql looks like this
SELECT p.ID FROM product p
LEFT JOIN availability a ON a.productID=p.ID
AND a.start>=DATE_ADD(DATE(now()), INTERVAL 7 DAY)
LEFT JOIN meta_data m ON m.ID=p.meta_dataID
WHERE a.ID IS NULL
AND m.published_state=1;
That is, find each Product with a MetaData.published_state equal to 1 and with no Availability such that Availability.start more than 7 days from now().
I'm trying to accomplish the same using ActiveRecord methods, using something like the following,
$products = Product::find()
->joinWith('metaData')
->joinWith('availability')
->onCondition(['>=', 'availability.start', strtotime('+7 days')])
->where(['is', 'availability.ID', NULL])
->andWhere(['=', 'meta_data.published_state', 1])
->all();
however, this is returning no results. Using Connection::createCommand() to run the raw sql returns the rows I'd expect so there is no issue with the data.
I suspect the issue is being caused by the join conditions and the where conditions 'bleeding' into each other; both join and where being applied to either the joining or the where rather than separately.
How can I output the actual sql query being run? this is in an action being called from a console controller.
How can I alter my code to return the desired Products?
I believe this one is better solution. Instead of using Raw queries like leftJoin you should complement your joinWith relations with andOnCondition (which adds needed where conditions into your join statement).
$products = Product::find()
->joinWith(['metaData' => function (ActiveQuery $query) {
return $query
->andWhere(['=', 'meta_data.published_state', 1]);
}])
->joinWith(['availability' => function (ActiveQuery $query) {
return $query
->andOnCondition(['>=', 'availability.start', strtotime('+7 days')])
->andWhere(['IS', 'availability.ID', NULL]);
}])
->all();
In addition it looks cleaner when you write where clauses inside relations. It works the same as writing it outside (if I'm not wrong), but when refactoring your query, you can easily delete the whole relation without forgetting relation conditions outside.
Just use like below condition.
$query = Product::find()
-> leftJoin('availability', 'availability.productID=product.ID AND a.start>=DATE_ADD(DATE(now()), INTERVAL 7 DAY)')
->leftJoin('meta_data', 'meta_data.ID=product.meta_dataID')
->where(['is', 'availability.ID', NULL])
->andWhere(['=', 'meta_data.published_state', 1])
->all();
Use this:
$sql = 'SELECT p.ID FROM product p
LEFT JOIN availability a ON a.productID=p.ID
AND a.start>=DATE_ADD(DATE(now()), INTERVAL 7 DAY)
LEFT JOIN meta_data m ON m.ID=p.meta_dataID
WHERE a.ID IS NULL
AND m.published_state=1';
$products = Product::findBySql($sql);
Yii Active Record has a findBySql($sql) method that allows you to run and get the data from database using a raw SQL query. It helps a lot when you got confused with Yii's query method or when your query get more complicated to be ran with Yii as in your case I suppose.
So basically, in above block of codes, you just put your raw SQL query to a variable called $sql, and use it as the parameter value of findBySql() method.

CodeIgniter Active Record or_where() function produces AND in sql?

I wrote an active record query in CodeIgniter and then I realised that I needed to use OR with to WHERE clauses. So I looked through the docs and found or_where which did what I wanted. But when I use it it produces AND in the output. I couldn't find any other questions on this issue.
I'm using CodeIgniter: 2.1.0
Here is my code (slightly cut down):
$this->db->select("p.*",false);
$this->db->from('projects p');
$this->db->join('customers c', 'p.c_id = c.c_id','left outer');
if(isset($options['add_root']))
$this->db->or_where('p.p_id=',1,FALSE);
//Get top level projects by default (1) or whatever parent is specified.
if(isset($options['p_id']))
$this->db->where('p.p_id=',$options['p_id'],false);
$query = $this->db->get();//query
I don't think you need or_where. I think you need better if/else in PHP.
The logic you probably want:
if(isset($options['p_id']))
{
// if p_id is set, then look for p_id
$this->db->where('p.p_id=',$options['p_id'],false);
// if p_id and add_root are set, then look for p_id OR p_id = 1
if(isset($options['add_root']))
$this->db->or_where('p.p_id=',1,FALSE);
}
elseif(isset($options['add_root']))
{
// look for p_id = 1 only
$this->db->where('p.p_id=',1,FALSE);
}
Because or_where is first it is simply defaulting to where, and then the subsequent where is the default: an "and".
You could also write the above with a series of elseif's but I view this as less clear:
if(isset($options['p_id']) && isset($options['add_root']))
$this->db
->where('p.p_id=',$options['p_id'],false)
->or_where('p.p_id=',1,FALSE);
elseif(isset($options['p_id']) || isset($options['add_root']))
$this->db
->where('p.p_id=',
// if add_root is set, then 1, otherwise p_id
(isset($options['add_root'])?1:$options['p_id']),false);
There's a small error in the order of the query that you're trying to run. You can add multiple 'where' clause which will get converted to a query with an 'AND' in between. But if you wanna use 'OR' instead you use a 'or_where'.
In your query you've used an 'or_where' clause, which is correct but you've used 'where' after that, which literally adds up to the previous query. So, you gotta use the 'where' clause first and then use the 'or_where' clause.
Just change the order and it would work.

Categories