Laravel Paginate with OrderBy - laravel

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

Related

Slow MySQL query in Laravel, but very fast in phpMyAdmin

I have worked with one query in Laravel, i need to optimize it. At first i have such query
DB::select(DB::raw("select `discounts`.`id`, `discounts`.`discount` from `discounts` left join `discount_companies_criteria` on `discounts`.`id` = `discount_companies_criteria`.`discount_id` and `discount_companies_criteria`.`is_active` = 1 where `discount_companies_criteria`.`company_id` is null and `discounts`.`status` = 1 group by `discounts`.`id`")) order by discounts.discount ASC;
laravel debugbar shows - 579ms
in phpmyadmin this query run by 503ms
than i have refactored code and get modified query (just remove sorting)
DB::select(DB::raw("select `discounts`.`id`, `discounts`.`discount` from `discounts` left join `discount_companies_criteria` on `discounts`.`id` = `discount_companies_criteria`.`discount_id` and `discount_companies_criteria`.`is_active` = 1 where `discount_companies_criteria`.`company_id` is null and `discounts`.`status` = 1 group by `discounts`.`id`")) ;
laravel debugbar shows - 579ms
in phpmyadmin this query run by 3ms
Can somebody explain, how i can get the same speed in laravel as in phpMyadmin?
Table discounts - 1900 rows
Table discount_companies_criteria - 7500000 rows
General tip, don't ever run query without limit "select, delete, or update", in your case use pagination
First the following query has no limit, which obviously would have bad performance depends on the size of the data you're dealing with:
SELECT `discounts`.`id`,
`discounts`.`discount`
FROM `discounts`
LEFT JOIN `discount_companies_criteria` ON `discounts`.`id` = `discount_companies_criteria`.`discount_id`
AND `discount_companies_criteria`.`is_active` = 1
WHERE `discount_companies_criteria`.`company_id` IS NULL
AND `discounts`.`status` = 1
GROUP BY `discounts`.`id`
The reason why this query or the other one are faster in phpMyAdmin is because phpMyAdmin by default set limit to the query.

How do I write this MySQL query in Laravel Eloquent?

I want to run
SELECT count(DISTINCT `ASIN`) as results FROM crawl_results WHERE user_id = 1 and website_id = 1
and expect to get 136 results
However
`select('ASIN')->where('user_id', Auth::id())->where('website_id', $scanID)->distinct()->count();`
returns all rows in the table of 814
and
`select('ASIN')->where('user_id', Auth::id())->where('website_id', $scanID)->groupby('ASIN')->count();`
returns 8 results
First create model and use the below code where you require it
use App\CrawlResult;
CrawlResult::where('user_id',1)->where('website_id',1)->distinct('ASIN')->count('ASIN');
You should write query like this:
DB::table('crawl_results')
->select(DB::raw('COUNT(DISTINCT(ASIN)) as results')
->where('user_id', 1)
->where('website_id',1)
->get();

Where clause is not fetching correct data in Laravel Eloquent

I am trying to get all articles which have 'approved' value in status column. Here is the code:
$articles = Article::where('status', 'approved')->orderBy('published_at', 'desc')->get();
But I am getting all data. where clause is not working! Is there anything wrong with the Syntax?
Edit 1:
Here is the what I'm getting for the query:
Edit 2:
Here are the columns I used in table.

Subtraction with aggregation using 2 tables

My Laravel query is not working properly. but MySQL query works fine
Laravel Query :
$data = DB::table(DB::raw('select (sum(case when type="credit" then amount else -amount end)) - (select sum(amount) from total) from report'))
Please refer mysql query in sqlfiidle : http://sqlfiddle.com/#!9/2d0343/9
Rather than try rewrite your MySQL query, let's simplify it and make it more eloquent.
Assuming $data is the overall balance and your model for the report table is called Report then the below should achieve what you are after:
$data = Report::where('type', 'credit')->sum('amount') - Report::where('type', 'debit')->sum('amount');
This will give you the sum of all your credits, minus the sum of all your debits.

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

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.

Resources