How do I return last n records in the order of entry - laravel

From Laravel 4 and Eloquent ORM - How to select the last 5 rows of a table, but my question is a little different.
How do I return last N records ordered in the way they were created (ASC).
So for example the following records are inserted in order:
first
second
third
fourth
fifth
I want a query to return last 2 records
fourth
fifth

Laravel Offset
DB::table('users')->skip(<NUMBER Calulation>)->take(5)->get();
You can calculate N by getting the count of the current query and skipping $query->count() - 5 to get the last 5 records or whatever you wanted.
Ex
$query = User::all();
$count = ($query->count()) - 5;
$query = $query->skip($count)->get();

In pure SQL this is done by using a subquery. Something like this:
SELECT * FROM (
SELECT * FROM foo
ORDER BY created_at DES
LIMIT 2
) as sub
ORDER BY created_at ASC
So the limiting happens in the subquery and then in the main query the order by is reversed. Laravel doesn't really have native support for subqueries. However you can still do it:
$sub = DB::table('foo')->latest()->take(2);
$result = DB::table(DB::raw('(' . $sub->toSql() . ') as sub'))
->oldest()
->get();
And if you use Eloquent:
$sub = Foo::latest()->take(2);
$result = Foo::from(DB::raw('(' . $sub->toSql() . ') as sub'))
->oldest()
->get();
Note the latest and oldest just add an orderBy('created_at) with desc and asc respectively.

Related

Laravel Paginate with OrderBy

When querying a product code table I have the following
$results = Stock::orderBy('stk_physical', 'desc')->paginate(10);
This works fine on the initial load of 10 records but when a subsequent call is made for page 2 I get the following error
Incorrect syntax near 'offset'. (SQL: select * from [stock_records] order by [stk_physical] desc offset 10 rows fetch next 10 rows only)
I'm using Laravel 8.0 with SQL
You should append query string to the pagination like this
$results = Stock::orderBy('stk_physical', 'desc')->paginate(10);
$results->appends(["order_by" => "stk_physical"]);
This will append the &order_by=stk_physical to each link in the view and you can also use withQueryString() to take in consideration query string in future pagination like this
$results = Stock::orderBy('stk_physical', 'desc')->paginate(10)->withQueryString();

Laravel query builder not getting results

I have a table with the following columns: model_id, starts and end
I'm looking to run a query tath finds all the rows that matches the provided model_id and have a start bigger and end lower that the provided code. Example: if the provided code is 15 and the model_id is 5 I should get all the rows that have model_id = 5 and start >= 15 and end <= 15.
This is th query I'm working with:
DB::table('generations')->where([['model_id', '=', 1],['starts', '>=', '1998'], ['end', '<=', '1998']])->get();
I transformed this to the raw sql but the returned sql query does not get any results too.
I'm using Laravel 5.7
Rows with model_id = 1;
your logic's order is the problem.
DB::table('generations')->where('model_id', '=', 1)->where('start', '<=', 1995)->where('end' , '>=', 1995)->get();
Learn more in the documentation.

problem of syntax in where clause when 2 columns are equal?

I have a filter on a form before displaying a list.
If the filter 'filter_parisetat' = 2, i set the where clause like this :
$query = $query->where('gri_nb_matchs','gri_nb_matchs_pec');
I want to select all the rows of my Grille table where 'gri_nb_matchs' equals 'gri_nb_matchs_pec'
but it doesn't work..nothing is selected (and of course in my table I have 10 in each columns for these 2 fields
The other Where conditions in case 1 is equal to
$query = $query->where('gri_nb_matchs','>','gri_nb_matchs_pec');
I should retrieve 0 rows, but here I retrieve all the rows..
it works upside down...
In My table, the 2 fields are described like this :
11 gri_nb_matchs tinyint(3) UNSIGNED
12 gri_nb_matchs_pec tinyint(3) UNSIGNED
In MySql, whenI write the query, results are correct..
What went wrong ?
Thanks a lot
Thierry
In this statement:
$query = $query->where('gri_nb_matchs','>','gri_nb_matchs_pec');
It seems you are comparing the field gri_nb_matchs to the string value 'gri_nb_matchs_pec', not the column named gri_nb_matchs_pec. In order to achieve this you have to use a raw query as so:
$query = $query->where('gri_nb_matchs','>',DB::raw('gri_nb_matchs_pec'));
or
$query = $query->whereRaw('gri_nb_matchs > gri_nb_matchs_pec');

laravel group by fetch latest record from table

I have one table where I want to retrieve data group by the user but I want the latest entry in result how can I do that by using eloquent.
here is an eloquent query I am using.
Product::whereNotNull('user_id')
->orderBy('id','desc')
->groupBy('user_id')
->get();
here is my table
Id Name user_id
-------------------------
1 A 1
2 b 1
3 c 2
4 d 2
5 e 3
6 f 3
result my query is giving me
Id Name user_id
-------------------------
1 A 1
3 c 2
5 e 3
result i want
Id Name user_id
-------------------------
2 b 1
4 d 2
6 f 3
Product::whereRaw('id IN (select MAX(id) FROM products GROUP BY user_id)')
->whereNotNull('user_id')
->orderBy('id','desc')
->get();
You will need a nested query for that, i don't think you can avoid it but this solution should work.
GroupBy happens before OrderBy so you have to get your last record before you do your ordering
Try this :
$subquery = Product::orderBy('id','DESC');
$products = DB::table(DB::raw("({$subquery->toSql()}) as subquery"))
->whereNotNull('user_id')
->groupBy('user_id')
->get();
2nd way : use unique() method in collection (The unique method returns all of the unique models in the collection):
$products = Product::whereNotNull('user_id')
->orderBy('id','desc')
->get()
->unique('user_id');
Check out Laravel Docs
latest / oldest
The latest and oldest methods allow you to easily order results by date. By default, result will be ordered by the created_at column. Or, you may pass the column name that you wish to sort by:
$product = Product::latest()->first();

Laravel Eloquent - Eager Loading Query is Being Restricted by limit()

I have the following query:
MyTable::where('my_column', '=', 25)->with('myOtherTable')
->orderBy('id', DESC)->limit(5);
I would like the above to bring me results analogoous to the following raw SQL query:
SELECT *
FROM myTable AS ABB1
LEFT JOIN myOtherTable AS ABB2 ON ABB1.id = ABB2.myTable_id
WHERE my_column = 25
ORDER BY myTable.id DESC
LIMIT 5;
The above will find everything in myTable along with corresponding info from myOtherTable and then limit the results to 5 rows.
When I run the eloquent statement above, two SQL queries are processed. The first looks something like:
SELECT *
FROM myTable
WHERE my_column = 25
ORDER BY id DESC;
If this query returns say 7 result items, but I pass in a smaller number into the limit() function (ie. limit(5)), then the corresponding eager loading query will look like:
SELECT *
FROM myOtherTable
WHERE id IN(1, 2, 3, 4, 5);
The eager loading query is itself limited to 5 items. There should be no limit here. The number of items in the IN conditional above should be 7 (or whatever the count returned from the first query is). The limit should only be applied after the second query runs.
How would I do this with Eloquent?
You can use eloquent's join.
MyTable::join('myOtherTable', 'column_id', '=', 'id')
->where('my_column', '=', 25)
->with('myOtherTable')
->orderBy('id', DESC)
->limit(5);
The with is only if you want to eager load the relation on MyTable.

Resources