CodeIgniter Group with SUM - codeigniter

I want to learn CodeIgniter, with an example case like this:
I have a database (tbl_points)
And I have an output like this:
id
sku
point
1
001
10
2
001
-1
3
002
5
4
002
-2
5
001
-1
I'm having a hard time making groups based on SKUs and then adding up each value at that point. Can you help me to make it like this? Thank you very much.
id
sku
point
1
001
8
2
002
3

If you want to write query for ci3.
$this->db->select('sku');
$this->db->select_sum('point');
$this->db->from('tbl_points');
$this->db->group_by('sku');
$query = $this->db->get();
$row = $query->result();
print_r($row);

This is resolved with a simple mysql SUM(), see Aggregate Function Descriptions
select * , sum(`point`) as my_point
from `tbl_points`
group by `sku`
in case you really need a new "id", you can extend your query using a User-Defined Variable to add on +1 for each new row:
set #row_num=0;
select * , sum(`point`) as my_point, #row_num:=#row_num+1 AS new_id
from `tbl_points`
group by `sku`
check the corresponding mysql fiddle
create that query with Codeigniter Query Builder
example for CI3.x:
$this->db->select('* , sum(point) as my_point');
$this->db->group_by('sku');
$query = $this->db->get('tbl_points');
and with the User-Defined Variable you need 2 queries, something like:
$sql="set #row_num:=0";
$this->db->query($sql);
$sql="select * , sum(`point`) as my_point, #row_num:=#row_num+1 AS new_id
from `tbl_points`
group by `sku`
";
$query=$this->db->query($sql);
to quickly output the result, you could write this line:
echo '<pre>';print_r($query->result());
anyway recommendable to check How to Generate CI Query Results

You need to sum it first, then group by this fields :-
$sql = "select id,sku, sum(`point`) as my_point from `tbl_points`
group by `sku`";
$query = $this->db->query($sql);
to output the result:-
echo '<pre>';
print_r($query->result());
Your Output result :-
id sku my_point
1 001 8
3 002 3

Related

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

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

Laravel: Sorting a column in the Left Join

Lets say I have a simple table of users
id | userName
3 Michael
4 Mike
5 George
And another table of their cars and prices
id | belongsToUser | carPrice
1 4 5000
2 4 6000
3 4 8000
I would like to do a left join that would return the highest or lowest carPrice
At the moment, the query would return the last/first instance of that users carPrice.
I've tried entering the orderBy in various join queries but to no avail.
I have a helper function that would return the highest/lowest price on demand but I'm not sure how that would fit within this query as I would like to use laravels inbuilt paginate
This is the aggregate problem so here is the solvation:
DB::table('users')
->leftJoin('carPrices', 'belongsToUser', '=', 'users.id')
->select('users.*', DB::raw('MAX(carPrice) as highestCarPrice'), DB::raw('MIN(carPrice) as lowestCarPrice'))
->groupBy('users.id')
->get();

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