MySQL LEFT JOIN example with conditions - mysql

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

Related

MySQL: From sub query to a single query

I have this query which i believe can be optimized:
SELECT floors.id, floors.floor FROM floors
WHERE floors.societies_id = 1
AND floors.status = 'Y'
AND floors.id NOT IN (
SELECT DISTINCT(floors.id) FROM floors
INNER JOIN societies ON societies.id = floors.societies_id
INNER JOIN resident_floors ON resident_floors.floors_id = floors.id
WHERE societies.id = 1
AND floors.status = 'Y'
)
Is this query fine to use or there it can be improved..?
It looks like you want to get all floors that aren't present in resident_floors. For this we can left join RF in and ask for only rows where the join failed resulting in a null in RF:
SELECT floors.* FROM floors
INNER JOIN societies ON societies.id = floors.societies_id
LEFT JOIN resident_floors ON resident_floors.floors_id = floors.id
WHERE societies.id = 1
AND floors.status = 'Y'
AND resident_floors.floors_id IS NULL

error subquery return more than 1 when doing multiple select

I want to do a multiple select in one query with different conditions. but somehow i'm stuck in this problem. any idea?
SELECT
(select io_link_event_names.name from doors left join controller_devices on doors.iid = controller_devices.iid left join events on controller_devices.mac = events.mac left join io_link_event_names on events.iolinkerid = io_link_event_names.extra where events.iolinkerid = "9000;1") AS forced,
(select doors.name FROM doors) AS doorname
ERROR #1242 - Subquery returns more than 1 row
consider this
SELECT d.[forced], doors.name as doorname
from doors
left join (
select controller_devices.iid, io_link_event_names.name as [forced]
from events
inner join controller_devices on controller_devices.mac = events.mac
inner join io_link_event_names on events.iolinkerid = io_link_event_names.extra
where events.iolinkerid = "9000;1"
) as d on d.iid = doors.iid
If you have more than 1 row in table doors, you get this error. If you want too see door name relevant to event selected in first query, use
select io_link_event_names.name,
doors.name doorname
from doors
left join controller_devices
on doors.iid = controller_devices.iid
left join events
on controller_devices.mac = events.mac
left join io_link_event_names
on events.iolinkerid = io_link_event_names.extra
where events.iolinkerid = "9000;1"

Mysql query with joined subqueries gives no result

i have a huge query:
SELECT stories.*
FROM stories stories
JOIN (SELECT tstories.uid
FROM stories tstories
JOIN tours_stories_mm mmt
ON tstories.uid = mmt.uid_foreign
JOIN tours tours
ON tours.uid = mmt.uid_local
JOIN tours_countries_rel tourcountryrel
ON tours.uid = tourcountryrel.tourid
JOIN countries tcountries
ON tcountries.uid = tourcountryrel.countryid
WHERE tcountries.uid = ?
AND tours.deleted = 0
AND tours.hidden = 0
AND tstories.deleted = 0
AND tstories.hidden = 0) as tourstories
JOIN (SELECT cstories.uid
FROM stories cstories
JOIN individualtourcomponents_stories_mm mmc
ON (cstories.uid = mmc.uid_foreign)
JOIN individualtourscomponents components
ON (components.uid = mmc.uid_local)
JOIN individualtourcomponents_countries_rel componentcountryrel
ON (components.uid = componentcountryrel.componentid)
JOIN countries ccountries
ON (ccountries.uid = componentcountryrel.countryid)
WHERE ccountries.uid = ?
AND components.deleted = 0
AND components.hidden = 0
AND cstories.deleted = 0
AND cstories.hidden = 0) as componentstories
WHERE stories.uid = componentstories.uid
OR stories.uid = tourstories.uid
GROUP BY stories.uid`
each of the subqueries work for themselves and if both subqueries have the same result, i get an result on the whole query. If only one subquery has a result i get nothing. Simplyfied it could be written like that:
SELECT stories.*
FROM stories
JOIN (SELECT * FROM table_a WHERE x=5) as table_a
JOIN (SELECT * form table_b where x=5) as table_b
WHERE stories.uid = table_a.uid OR stories.uid = table_b.uid
GROUP BY stories.uid
What am i doing wrong?
It seems like you should be using an OUTER JOIN instead of INNER JOIN to join your source tables.
Using the simplified query example, it might look like this:
SELECT stories.*
FROM stories
LEFT OUTER JOIN (SELECT * FROM table_a WHERE x=5) as table_a
ON stories.uid = table_a.uid
LEFT OUTER JOIN (SELECT * form table_b where x=5) as table_b
ON stories.uid = table_b.uid
GROUP BY stories.uid
UPDATE
Based on your comment it sounds like you actually want to get the distinct union of the the two sub queries.
If that's the case, you could modify your original query like this:
(SELECT tstories.*
FROM stories tstories
JOIN tours_stories_mm mmt
ON tstories.uid = mmt.uid_foreign
JOIN tours tours
ON tours.uid = mmt.uid_local
JOIN tours_countries_rel tourcountryrel
ON tours.uid = tourcountryrel.tourid
JOIN countries tcountries
ON tcountries.uid = tourcountryrel.countryid
WHERE tcountries.uid = ?
AND tours.deleted = 0
AND tours.hidden = 0
AND tstories.deleted = 0
AND tstories.hidden = 0
)
UNION DISTINCT
(SELECT cstories.*
FROM stories cstories
JOIN individualtourcomponents_stories_mm mmc
ON (cstories.uid = mmc.uid_foreign)
JOIN individualtourscomponents components
ON (components.uid = mmc.uid_local)
JOIN individualtourcomponents_countries_rel componentcountryrel
ON (components.uid = componentcountryrel.componentid)
JOIN countries ccountries
ON (ccountries.uid = componentcountryrel.countryid)
WHERE ccountries.uid = ?
AND components.deleted = 0
AND components.hidden = 0
AND cstories.deleted = 0
AND cstories.hidden = 0
)

MySQL - WHERE every value is IN

The following query selects all workunts where the inputs are "done" (subquery on line 7). This works fine... when there is only one input. How can I change this so that it requires every input to be IN that set returned by the subquery, not just one of the inputs to be present?
SELECT workunits.ID
FROM workunits
LEFT JOIN workunitInputs ON workunits.ID = workunitInputs.workunitID
WHERE workunits.ID NOT IN (SELECT workunitID FROM jobworkunitassoc)
AND (
workunitInputs.inputID IN (
SELECT workunitOutputs.outputID
FROM workunitOutputs
LEFT JOIN workunits ON workunitOutputs.workunitID = workunits.ID
LEFT JOIN jobworkunitassoc ON workunits.ID = jobworkunitassoc.workunitID
LEFT JOIN jobs ON jobworkunitassoc.jobID = jobs.ID
WHERE jobs.done = 1
)
OR workunitInputs.inputID IS NULL
)
GROUP BY workunits.ID
Thanks, Istvan.
Change that clause to:
AND (
workunitInputs.inputID NOT IN (
SELECT workunitOutputs.outputID
FROM workunitOutputs
LEFT JOIN workunits ON workunitOutputs.workunitID = workunits.ID
LEFT JOIN jobworkunitassoc ON workunits.ID = jobworkunitassoc.workunitID
LEFT JOIN jobs ON jobworkunitassoc.jobID = jobs.ID
WHERE jobs.done != 1
)
This is based on the logical tautology: All X in Y === No X in !Y
This query works for me, though it may not be the best solution:
http://pastebin.com/g9qBjQGU

Getting unique values with SUM and JOIN

I'm trying to get the total of calc.transport
Table 3_product_folder contains duplicate values (column 'folder_id'), how can I prevent the from messing up the SUM?
I have tried DISTINCT with no succes.
Any suggestions?
SELECT
SUM(calc.transport) AS transport
FROM 0_calculatie_id AS calc
LEFT JOIN 0_calculatie_inh_id AS id
ON id.calculatie_id = calc.id
LEFT JOIN 3_product_folder AS fld_id
ON fld_id.product_id = id.id
LEFT JOIN 4_folder_dossier AS fld
ON fld.product_folder_id = fld_id.folder_id
LEFT JOIN 10_factuur_inh AS fac_inh
ON fac_inh.folder_id = fld.id
LEFT JOIN 9_factuur_id AS fac
ON fac.id = fac_inh.factuur_id
WHERE YEAR(fac.datum_verstuurd) = ".$row['jaar']." AND MONTH(fac.datum_verstuurd) = ".$row_mth2['maand']."
I have tried this nested query but that not all items are calculated then:
SELECT
SUM(temp.transport) AS transport
FROM
(SELECT DISTINCT
calc.transport,
fld_id.folder_id
FROM 0_calculatie_id AS calc
LEFT JOIN 0_calculatie_inh_id AS id
ON id.calculatie_id = calc.id
LEFT JOIN 3_product_folder AS fld_id
ON fld_id.product_id = id.id
LEFT JOIN 4_folder_dossier AS fld
ON fld.product_folder_id = fld_id.folder_id
LEFT JOIN 10_factuur_inh AS fac_inh
ON fac_inh.folder_id = fld.id
LEFT JOIN 9_factuur_id AS fac
ON fac.id = fac_inh.factuur_id
WHERE YEAR(fac.datum_verstuurd) = 2012 AND MONTH(fac.datum_verstuurd) = 7) AS temp
what the structure of the table?
you haven't grouped the SQL statement:
WHERE YEAR(fac.datum_verstuurd) = ".$row['jaar']." AND MONTH(fac.datum_verstuurd) = ".$row_mth2['maand']."
GROUP BY fld_id.product_id