Laravel Eloquent - 2 seperate table with own left join - mysql

I have the following 4 tables
aa:id, xx_id, bb_id
bb:id
xx:id, zz_id
zz.id
I would like to do a query like this
SELECT *
FROM
aa LEFT JOIN bb ON (aa.bb_id = bb.id),
xx LEFT JOIN zz ON (xx.zz_id = zz.id)
WHERE aa.xx_id = xx.id
How do I achieve this through Laravel Eloquent?

Since using a comma to separate tables in the FROM clause is the same as using a CROSS JOIN, you should first rewrite your query to use a CROSS JOIN.
SELECT *
FROM
(SELECT * FROM aa LEFT JOIN bb ON aa.bb_id = bb.id) T1
CROSS JOIN
(SELECT * FROM xx LEFT JOIN zz ON xx.zz_id = zz.id) T2
WHERE
aa.xx_id = xx.id
// First define the subqueries.
$t1 = DB::table('aa')->leftJoin('bb', 'aa.bb_id', 'bb.id');
$t2 = DB::table('xx')->leftJoin('zz', 'xx.zz_id', 'zz.id');
// Do the query.
$results = DB::table($t1, 'T1')
->crossJoinSub($t2, 'T2')
->whereColumn('aa.x_id', 'xx.id')
->get();
Alternatively, you can pass the whole FROM clause to the fromRaw method.
$results = DB::query()
->fromRaw('aa LEFT JOIN bb ON (aa.bb_id = bb.id), xx LEFT JOIN zz ON (xx.zz_id = zz.id)')
->whereColumn('aa.x_id', 'xx.id')
->get();

Related

Show all records using INNER JOIN

I am familiar with INNER JOIN just enough to understand the basics. But is there a way that I can select all records from both tables without cluttering the SQL sting with each column name. I was thinking in the line with the below code
SELECT * FROM new_case
INNER JOIN dispatch
ON new_case.file_nr = dispatch.case_nr
WHERE new_case.id = '27'
This is what i'd try;
SELECT ft.*, af.* FROM new_case ft INNER JOIN dispatch af ON (ft.file_nr = af.case_nr) WHERE new_case.id = '27'
Results from both tables:
SELECT nc.*, d.*
FROM new_case nc
INNER JOIN dispatch d
ON nc.file_nr = d.case_nr
WHERE nc.id = '27'

How can I optimize this mysql query

I would like to ask, how can I optimize this query:
select
h.jmeno hrac,
n1.url hrac_url,
t.nazev tym,
n2.url tym_url,
ss.pocet_zapasu zapasy,
ss.pocet_minut minuty,
s.celkem_golu goly,
s.zk,
s.ck
from
hraci h
left join
(
select
hrac_id,
tym_id,
count(minut_celkem) pocet_zapasu,
sum(minut_celkem) pocet_minut
from
statistiky_stridani ss
join
zapasy z
on z.id = ss.zapas_id
join
souteze s
on s.id = z.soutez_id
join
souteze_nazev sn
on sn.id = s.soutez_id
where
s.rocnik_id = 2
group by
hrac_id
) ss on ss.hrac_id = h.id
left join
(
select
hrac_id,
tym_id,
sum(typ_id = 1 or typ_id = 3) as celkem_golu,
sum(typ_id = 4) as zk,
sum(typ_id = 5) as ck
from
statistiky st
join
zapasy z
on z.id = st.zapas_id
join
souteze s
on s.id = z.soutez_id
join
souteze_nazev sn
on sn.id = s.soutez_id
where
s.rocnik_id = 2
group by
hrac_id
) s on s.hrac_id = h.id
join
navigace n1
on n1.id = h.nav_id
join
tymy t
on t.id = ss.tym_id
join
navigace n2
on n2.id = t.nav_id
order by
s.celkem_golu desc
limit
10
Because query takes about 1,5 - 2 seconds. For example, table statistiky_stridani has about 500 000 rows and statistiky about 250 000 rows.
This returns EXPLAIN:
Thank you for your help
Don't use LEFT JOIN instead of JOIN unless you really need the empty rows.
Try to reformulate because JOIN ( SELECT ... ) JOIN ( SELECT ... ) optimizes poorly.
Please do not use the same alias (s) for two different tables; it confuses the reader.
Add the composite index INDEX(rocnik_id, soutez_id) to souteze.
LEFT JOIN ... JOIN ... -- Please add parentheses to show whether the JOIN should be before doing the LEFT JOIN or after:
either
FROM ...
LEFT JOIN ( ... JOIN ... )
or
FROM ( ... LEFT JOIN ... )
JOIN ...
It may make a big difference in how the Optimizer performs the query, which may change the speed.
There may be more suggestions; work through those and ask again (if it is still "too slow").

MySQL LEFT JOIN example with conditions

I am using following query to retrieve the needed objects:
SELECT *
FROM tb_po_items
LEFT JOIN tb_materials ON tb_po_items.po_material = tb_materials.id_material
LEFT JOIN tb_services ON tb_po_items.po_service = tb_services.id_service
WHERE po_id =47
Now I need to add following:
Condition 1 -> if tb_po_items.mos = 1 then LEFT JOIN tb_units ON tb_materials.material_unit = tb_units.id_unit
else
Condition 2 -> if tb_po_items.mos = 2 then LEFT JOIN tb_units ON tb_services.service_unit = tb_units.id_unit
How can I implement the use of both conditions in the MySQL query?
Thanks in advance.
Try this:
SELECT *
FROM tb_po_items
LEFT JOIN tb_materials ON tb_po_items.po_material = tb_materials.id_material
LEFT JOIN tb_services ON tb_po_items.po_service = tb_services.id_service
LEFT JOIN tb_units ON (
(tb_materials.material_unit = tb_units.id_unit AND tb_po_items.mos = 1)
OR
(tb_services.service_unit = tb_units.id_unit AND tb_po_items.mos = 2) )
WHERE po_id =47;
hi this is experimental so check before you go live.
SELECT * FROM tb_po_items
IF(tb_po_items.mos = 1, LEFT JOIN tb_materials ON tb_po_items.po_material = tb_materials.id_material, LEFT JOIN tb_services ON tb_po_items.po_service = tb_services.id_service)
WHERE po_id =47

Joining in the row with max value via a jointable

Usually when I need to join the row with some max value from another column I do something like:
SELECT *
FROM a
INNER JOIN b ON (a.aid = b.aid)
LEFT JOIN b nullb ON (a.aid = nullb.aid AND nullb.value > b.value)
WHERE nullb.bid IS NULL;
I'm not sure if this is the most efficent way but it is a solution without subqueries which i avoid whenever possible.
Today I needed to join in the max value from another table that joins in via a jointable and could not figure out a way to do it.
I tried something like this: (which failed miserably)
SELECT *
FROM a
INNER JOIN atob ON (a.aid = atob.aid)
INNER JOIN b ON (atob.bid = b.bid)
LEFT JOIN atob nullatob ON (a.aid = nullatob.aid)
LEFT JOIN b nullb ON (nullatob.bid = nullb.bid AND nullb.value > b.value)
WHERE nullb.bid IS NULL;
I set up an sqlfiddle at: http://sqlfiddle.com/#!9/86f18/6 with the problem set up.
Anyone got a clever way to join in the max value from another table via a jointable without using subqueries or is that pretty much impossible?
Not sure what is your goal but:
http://sqlfiddle.com/#!9/86f18/13
SELECT A.*, b.*
FROM A
INNER JOIN AtoB
ON (A.Aid = AtoB.Aid)
LEFT JOIN (
SELECT B.*
FROM B
LEFT JOIN b nullB
ON (B.Bid = nullB.Bid AND nullB.bdate > B.Bdate)
WHERE nullB.Bid IS NULL
) b
ON AtoB.Bid = b.Bid

Mysql Left Join does not return all values

I have a simple mysql query that work fine but it does not return all the values . All the values are returned when I use the left joined table alone but when I add the other tables only those that are all "=" return a value. Here is the query:
SELECT
d.flight_no , b.arrival_flight
FROM
jtl_booking_transfer_details AS b
LEFT JOIN jtl_flight_info AS d
ON (d.flight_no b.arrival_flight),
jtl_booking_master a,
jtl_hotels c,
jtl_airlines e
WHERE
a.voucher_number = b.voucher_number AND
b.hotel_id = c.hotel_id AND
e.airline_code = d.airline_code
Use the same syntax for getting all tables (easier to read : JOIN for ... joining tables, WHERE clause for other predicates)
SELECT
d.flight_no , b.arrival_flight
FROM
jtl_booking_transfer_details b
LEFT JOIN jtl_flight_info d
ON d.flight_no = b.arrival_flight
LEFT JOIN jtl_booking_master a
ON a.voucher_number = b.voucher_number
LEFT JOIN jtl_hotels c
ON b.hotel_id = c.hotel_id
LEFT JOIN jtl_airlines e
ON e.airline_code = d.airline_code