laravel eloquent relation with 3 table - laravel-5

Hi I want query from 3 table
user:
+----+-----------+
| id | name |
+----+-----------+
| 1 | Denny |
| 2 | Agus |
| 3 | Dini |
| 4 | Angel |
+----+-----------+
History_Education
+----+-----------+-------------+
| id | userId | educationId |
+----+-----------+-------------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
| 4 | 2 | 2 |
+----+-----------+-------------+
Education
+----+-----------+----------+
| id | level | Name |
+----+-----------+----------+
| 1 | 1 | SD |
| 2 | 2 | SMP |
| 3 | 3 | SMA |
| 4 | 4 | S1 |
+----+-----------+----------+
How to query with laravel Eloquent to get the latest user education order by Level DESC
expected:
+----+-----------+----------------------+
| id | Name | Latest_Education |
+----+-----------+----------------------+
| 1 | Denny | SMP |
| 2 | Agus | SMP |
| 3 | Dini | - |
| 4 | Angel | - |
+----+-----------+----------------------+
In normal query:
select id,name ,(select E.name from education E inner join History_eductaion HE on E.id = HE.education_id where HE.userId =U.id limit 1 order by E.level DESC )latest_education from USER U
How to translate to laravel eloquent?

The quick answer is use the query builder - your query needed to be altered slightly to match the table names and columns as listed in your question:
$result = DB::table('user')
->select([
'id',
'name',
DB::raw("(select E.name from Education E inner join History_Education HE on E.id = HE.educationId where HE.userId = user.id order by E.level DESC limit 1) as latest_education")
])
->get();

Related

Laravel Select unique count with groupBy

I am trying to get the count of unique batches in gift_code table for each campaign. The gift_code table is joined to campaign table by campaign_id.
Here is some sample data for campaign table.
--------------+--------------
|campaign_id | name |
--------------+--------------
| 1 | abc |
--------------+--------------
| 2 | xyz |
--------------+--------------
Below is some sample data for gift_code table.
--------------+------------------------+--------------+
|gift_code_id | campaign_id | batch | unique_code |
--------------+-------------+----------+---------------
| 1 | 1 | 1 | zxc23 |
--------------+-------------+----------+--------------+
| 2 | 1 | 2 | rtc26 |
--------------+-------------+----------++-------------+
| 3 | 2 | 1 | z8723 |
--------------+-------------+----------+--------------+
| 4 | 2 | 2 | h7c26 |
--------------+-------------+----------++-------------+
| 5 | 2 | 2 | rrcf6 |
--------------+-------------+----------++-------------+
| 6 | 2 | 3 | r7y28 |
--------------+-------------+----------++-------------+
| 7 | 2 | 3 | bnc26 |
--------------+-------------+----------++-------------+
$campaign = DB::table('campaign')
->select('campaign.*', DB::raw('count(gift_code.batch) as batch_count')->groupBy('gift_code.campaign_id')->groupBy('gift_code.batch'))
->leftjoin('gift_code', 'campaign.campaign_id', '=', 'gift_code.campaign_id')
->get();
My expected results are:
--------------+-------------------------+
|campaign_id | name |batch_count|
--------------+-------------+-----------+
| 1 | abc | 2 |
--------------+-------------+-----------+
| 2 | xyz | 3 |
--------------+-------------+-----------+
Try below query
$data = \DB::table('campaign as c')
->leftJoin('gift_code as gc','c.campaign_id','=','gc.campaign_id')
->select('c.*',\DB::raw('COUNT(distinct(gc.batch)) as batch_count'))
->groupBy('c.campaign_id')
->get();

Determinate unique values from oracle join?

I need a way to avoid duplicate values from oracle join, I have this scenario.
The first table contain general information about a person.
+-----------+-------+-------------+
| ID | Name | Birtday_date|
+-----------+-------+-------------+
| 1 | Byron | 12/10/1998 |
| 2 | Peter | 01/11/1973 |
| 4 | Jose | 05/02/2008 |
+-----------+-------+-------------+
The second table contain information about a telephone of the people in the first table.
+-------+----------+----------+----------+
| ID |ID_Person |CELL_TYPE | NUMBER |
+-------+- --------+----------+----------+
| 1221 | 1 | 3 | 099141021|
| 2221 | 1 | 2 | 099091925|
| 3222 | 1 | 1 | 098041013|
| 4321 | 2 | 1 | 088043153|
| 4561 | 2 | 2 | 090044313|
| 5678 | 4 | 1 | 092049013|
| 8990 | 4 | 2 | 098090233|
+----- -+----------+----------+----------+
The Third table contain information about a email of the people in the first table.
+------+----------+----------+---------------+
| ID |ID_Person |EMAIL_TYPE| Email |
+------+- --------+----------+---------------+
| 221 | 1 | 1 |jdoe#aol.com |
| 222 | 1 | 2 |jdoe1#aol.com |
| 421 | 2 | 1 |xx12#yahoo.com |
| 451 | 2 | 2 |dsdsa#gmail.com|
| 578 | 4 | 1 |sasaw1#sdas.com|
| 899 | 4 | 2 |cvcvsd#wew.es |
| 899 | 4 | 2 |cvsd#www.es |
+------+----------+----------+---------------+
I was able to produce a result like this, you can check in this link http://sqlfiddle.com/#!4/8e326/1
+-----+-------+-------------+----------+----------+----------+----------------+
| ID | Name | Birtday_date| CELL_TYPE| NUMBER |EMAIL_TYPE|EMAIL|
+-----+-------+-------------+----------+----------+----------+----------------+
| 1 | Byron | 12/10/1998 | 3 | 099141021|1 |jdoe#aol.com |
| 1 | Byron | 12/10/1998 | 2 | 099091925|2 |jdoe1#aol.com |
| 1 | Byron | 12/10/1998 | 1 | 099091925| | |
| 2 | Peter | 01/11/1973 | 1 | 088043153|1 |xx12#yahoo.com |
| 2 | Peter | 01/11/1973 | 2 | 090044313|2 |dsdsa#gmail.com |
| 4 | Jose | 05/02/2008 | 1 | 092049013|1 |sasaw1#sdas.com |
| 4 | Jose | 05/02/2008 | 2 | 098090233|2 |cvcvsd#wew.es |
+-----+-------+-------------+----------+----------+----------+----------------+
If you check the data in table Email for user with ID_Person = 4 only present two of the three emails that have, the problem for this case is the person have more emails that cellphone numbers and only will present the same number of the cellphone numbers.
The result i expected is something like this.
+-----+-------+-------------+----------+----------+----------+----------------+
| ID | Name | Birtday_date| CELL_TYPE| NUMBER |EMAIL_TYPE|EMAIL|
+-----+-------+-------------+----------+----------+----------+----------------+
| 1 | Byron | 12/10/1998 | 3 | 099141021|1 |jdoe#aol.com |
| 1 | Byron | 12/10/1998 | 2 | 099091925|2 |jdoe1#aol.com |
| 1 | Byron | 12/10/1998 | 1 | 099091925| | |
| 2 | Peter | 01/11/1973 | 1 | 088043153|1 |xx12#yahoo.com |
| 2 | Peter | 01/11/1973 | 2 | 090044313|2 |dsdsa#gmail.com |
| 4 | Jose | 05/02/2008 | 1 | 092049013|1 |sasaw1#sdas.com |
| 4 | Jose | 05/02/2008 | 2 | 098090233|2 |cvcvsd#wew.es |
| 4 | Jose | 05/02/2008 | | |2 |cvsd#www.es |
+-----+-------+-------------+----------+----------+----------+----------------+
This is the way that i need to present the data.
I could not understand why your query was so complex, thus, added the simple full outer join and it seems to be working:
select distinct p.id, p.name,
case when Lag(CELL) over(partition by p.id order by p.id,pe.id) = CELL then null else cell_type end as cell_type,
case when Lag(CELL) over(partition by p.id order by p.id,pe.id) = CELL then null else CELL end as CELL,
EMAIL_TYPE as EMAIL_TYPE, EMAIL as EMAIL
from person p full outer join phones pe on p.id = pe.id
full outer join emails e
on p.id = e.id and pe.cell_type = e.email_type;

Eloquent Joins and Sums

I have 2 tables and would like to get have a query which gets all columns from table 'projects' and several sums from table 'invoices' based on a field 'type'.
projects
+----+--------+------+--------+
| ID | Address| Date | Other |
+----+--------+------+--------+
| 1 | demo | date | other |
| 2 | demo2 | date2| other2 |
invoices
+----+---------+-----+--------+
| ID | proj_id | type| amount |
+--------------+-----+--------+
| 1 | 1 | a | 10 |
| 2 | 1 | a | 20 |
| 3 | 1 | b | 10 |
| 4 | 1 | b | 15 |
| 5 | 1 | c | 5 |
| 6 | 2 | a | 30 |
| 7 | 2 | a | 5 |
| 8 | 2 | b | 30 |
| 9 | 2 | c | 5 |
| 10 | 2 | c | 30 |
Using Laravel Eloquent I want to be able to get:
+----+---------+------+-------+---+---+---+
| ID | Address | Date | Other | a | b | c |
+----+---------+------+-------+---+---+---+
| 1 | demo | date | other |30 |25 | 5 |
| 2 | demo2 | date2| other2|35 |30 |35 |
Im getting stuck with the sum part, well actually the whole thing!
So far I have:
$projects = DB::table('projects')
->leftJoin('invoices', 'projects.id', '=', 'invoices.project_id')
->select('projects.*', 'invoices.*')
->get();
Which is obviously not very far along! Any help would be greatly appreciated!
You need a basic pivot query here. The easiest way to go here would probably be via a raw select:
$sql = "projects.*, ";
$sql .= "sum(case when invoices.type = 'a' then invoices.amount end) as a, ";
$sql .= "sum(case when invoices.type = 'b' then invoices.amount end) as b, ";
$sql .= "sum(case when invoices.type = 'c' then invoices.amount end) as c";
$projects = DB::table('projects')
->select(DB::raw($sql))
->leftJoin('invoices', 'projects.id', '=', 'invoices.project_id')
->groupBy('project.id')
->get();
This should correspond to the following raw MySQL query:
SELECT
p.*,
SUM(CASE WHEN i.type = 'a' THEN i.amount END) AS a,
SUM(CASE WHEN i.type = 'b' THEN i.amount END) AS b,
SUM(CASE WHEN i.type = 'c' THEN i.amount END) AS c
FROM project p
LEFT JOIN invoices I
ON p.id = i.project_id
GROUP BY
p.id;

How to get the max value for elements having the same id under Laravel

Using Laravel/Eloquent, I would like to retrieve the max value for each week_id in the following table.
+---------+-----------+
| week_id | value |
+---------+-----------+
| 5 | |
| 6 | 1 |
| 6 | |
| 6 | |
| 7 | 3 |
| 7 | 4 |
| 7 | |
+---------+-----------+
With MySql I would do it like this:
SELECT week_id, max(value) as max_value FROM foo_table GROUP BY week_id
=>
+---------+-----------+
| week_id | max_value |
+---------+-----------+
| 5 | |
| 6 | 1 |
| 7 | 4 |
+---------+-----------+
How could I achieve the same under Laravel?
Try this:
DB::table('foo_table')
->select('week_id', DB:raw('max(value) as max_value'))
->groupBy('week_id')
->get();

laravel, group by category and select the record with the minimum price

I have models Book and BookCategory
How do I select the cheapest book in every category?
Book table:
| id | name | price | book_category_id |
| 1 | test | 10 | 1
| 2 | test | 15 | 3
| 3 | test | 75 | 1
| 4 | test | 25 | 2
| 5 | test | 19 | 1
| 6 | test | 11 | 2
| 7 | test | 10 | 1
The selection should be :
| id | name | price | book_category_id |
| 1 | test | 10 | 1
| 2 | test | 15 | 3
| 6 | test | 11 | 2
I've tried:
$books = Book::groupBy("book_category_id")->orderBy("price")->get()
But the output is not the minimum price row.
any idea?
EDIT:
I found this page:
https://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/
it has 90% of the solution in SQL
SELECT *
FROM books
WHERE price = (SELECT MIN(price) FROM books AS u WHERE u.book_category_id= books.book_category_id)
GROUP BY books.book_category_id
how to convert this to laravel query builder?
You need to perform a subquery like this post. Try this:
$books = Book::from(DB::raw("SELECT * FROM books order by price asc"))
->groupBy("book_category_id")->get();
Please note that this is a mysql only solution because in mysql you're allowed to not aggregate non-group-by columns. If you need to do this for another DB, you need to perform an inner join on the subquery

Resources