Left Join inside the same table SQL - mysql

SELECT
`_conf_cities`.`cityid`,
`_conf_cities`.`countryid`,
`_conf_cities`.`name_mkd`,
`_conf_cities`.`child_municipality`,
`_conf_cities`.`parent`,
`conf_countries`.`countryid`,
`conf_countries`.`alpha2`
FROM `_conf_cities`
LEFT JOIN `conf_countries` ON `_conf_cities`.`countryid` = `conf_countries`.`countryid`
LEFT JOIN `_conf_cities` ON `_conf_cities`.`cityid` = `_conf_cities`.`parent`
WHERE `_conf_cities`.`child_municipality` = '0'
The problem occurs when I try to LEFT JOIN _conf_cities to itself.
Can this be done another way?

You have to use alias, like:
SELECT
_conf_cities.cityid,
_conf_cities.countryid,
_conf_cities.name_mkd,
_conf_cities.child_municipality,
_conf_cities.parent,
conf_countries.countryid,
conf_countries.alpha2,
t2.cityid -- Now you can use alias
FROM _conf_cities
LEFT JOIN conf_countries ON _conf_cities.countryid = conf_countries.countryid
LEFT JOIN _conf_cities AS t2 ON _conf_cities.cityid = t2.parent
WHERE
_conf_cities.child_municipality = '0'
AND t2.child_municipality = '0' -- Also you can use alias here

Related

Apply if row exist function on left join

I'm combining 3-6 tables using left join. Here's some example of the code on from clause
FROM ip_ucp_01
LEFT JOIN ip_lt_01
ON ip_ucp_01.time = ip_lt_01.time
AND ip_ucp_01.date = ip_lt_01.date
LEFT JOIN ip_le
ON ip_lt_01.time = ip_le.time
AND ip_lt_01.date = ip_le.date
LEFT JOIN ip_lmiv_01
ON ip_le.time = ip_lmiv_01.time
AND ip_le.date = ip_lmiv_01.date
LEFT JOIN ip_cwg
ON ip_lmiv_01.time = ip_cwg.time
AND ip_lmiv_01.date = ip_cwg.date
LEFT JOIN ip_mtu_01
ON ip_cwg.time = ip_mtu_01.time
AND ip_cwg.date = ip_mtu_01.date
if there is no row on second table and third table, the data forth table and so on won't be displayed. I need to check whether the row on second table is exist or not. If so, it will use left join second table, if not it will use left join on third table and so on.
How about if you just JOIN with your first table? Like this:
FROM ip_ucp_01
LEFT JOIN ip_lt_01
ON ip_ucp_01.time = ip_lt_01.time
AND ip_ucp_01.date = ip_lt_01.date
LEFT JOIN ip_le
ON ip_ucp_01.time = ip_le.time
AND ip_ucp_01.date = ip_le.date
LEFT JOIN ip_lmiv_01
ON ip_ucp_01.time = ip_lmiv_01.time
AND ip_ucp_01.date = ip_lmiv_01.date
LEFT JOIN ip_cwg
ON ip_ucp_01.time = ip_cwg.time
AND ip_ucp_01.date = ip_cwg.date
LEFT JOIN ip_mtu_01
ON ip_ucp_01.time = ip_mtu_01.time
AND ip_ucp_01.date = ip_mtu_01.date
since you only join on date and time won't this do what you want?
I don't think LEFT JOIN will work the way your are asking for ,because if there is no entry in parent table your won't be able to fetch data from grandchild .
In my opinion you can simple use CASE with Count (not best practice) but it will solve your problem.
You can use separate SELECT queries for those JOINs and UNION them all (with DISTINCT) into one query, e.g.:
SELECT DISTINCT column_name
FROM (
SELECT column_name
FROM ip_ucp_01
LEFT JOIN ip_lt_01 ON ip_ucp_01.time = ip_lt_01.time AND ip_ucp_01.date = ip_lt_01.date
LEFT JOIN ip_le ON ip_lt_01.time = ip_le.time AND ip_lt_01.date = ip_le.date;
UNION
SELECT column_name
FROM ip_ucp_01
LEFT JOIN ip_lmiv_01 ON ip_ucp_01.time = ip_lmiv_01.time AND ip_ucp_01.date = ip_lmiv_01.date
) a;

How to join a table with a result field of a condition in MySQL

I have an SQL query where in my SELECT part I have a column which is a result of an IF statement. As you can see 'final_vendor_id' contains the value of ioproductrel.vendorid except when it's value is null or 0, because in this case the value of products.vendor_id is used:
SELECT
IF(ioproductrel.vendorid IS NULL OR ioproductrel.vendorid = 0, products.vendor_id, ioproductrel.vendorid) AS 'final_vendor_id',
account.accountname AS 'account',
salesorder.duedate
FROM
internalorder LEFT JOIN ioproductrel ON internalorder.internalorderid = ioproductrel.internalorderid
LEFT JOIN products ON ioproductrel.productid = products.productid
LEFT JOIN slip_relations ON internalorder.internalorderid = slip_relations.child_crmid
INNER JOIN salesorder ON slip_relations.parent_crmid = salesorder.salesorderid
LEFT JOIN account ON salesorder.accountid = account.accountid
LEFT JOIN account AS acc2 ON acc2.accountid = final_vendor_id
WHERE
internalorder.internalorderid = 8982
I want to join a table based on this 'final_vendor_id', but I just get an error that no field with such a name exists.
If I write the whole IF statement in the JOIN part again, it seems to work but Im not sure if it is safe and Im wondering if is there any simplier way than this:
SELECT
IF(ioproductrel.vendorid IS NULL OR ioproductrel.vendorid = 0, products.vendor_id, ioproductrel.vendorid) AS 'final_vendor_id',
account.accountname AS 'account',
salesorder.duedate
FROM
internalorder LEFT JOIN ioproductrel ON internalorder.internalorderid = ioproductrel.internalorderid
LEFT JOIN products ON ioproductrel.productid = products.productid
LEFT JOIN slip_relations ON internalorder.internalorderid = slip_relations.child_crmid
INNER JOIN salesorder ON slip_relations.parent_crmid = salesorder.salesorderid
LEFT JOIN account ON salesorder.accountid = account.accountid
LEFT JOIN account AS acc2 ON acc2.accountid = IF(ioproductrel.vendorid IS NULL OR ioproductrel.vendorid = 0, products.vendor_id, ioproductrel.vendorid)
WHERE
internalorder.internalorderid = 8982
What if set single quotes in left join section like:
...ON acc2.accountid = 'final_vendor_id'

IF/ELSE LEFT JOIN

I need to do a LEFT JOIN with IF/ELSE, this is my query:
IF (M.idArtVar=null,
LEFT JOIN ArtMaga G
ON (G.idMagazzino = V.idMagazzino AND G.idArticolo = M.idArticolo),
LEFT JOIN ArtMaga G
ON (G.idMagazzino = V.idMagazzino AND G.idArticolo = M.idArticolo AND
G.idArtVar = M.idArtVar)
)
But it doesn't work.
I also tried like this:
LEFT JOIN ArtMaga AM
ON IF(M.idArtVar IS NULL,
(AM.idMagazzino = TM.idMagazzino AND AM.idArticolo = A.idArticoli),
(AM.idMagazzino = TM.idMagazzino AND AM.idArtVar = M.idArtVar))
But this query is too slow.
How can I do?
Thanks.
EDIT: This is full query:
SELECT F.Codice AS "CodiceFornitore", F.RagioneSociale AS "RagioneSocialeFornitore", A.ArticoloFornitore, C.Descrizione AS CatDes, S.Descrizione AS Settore, U.Sigla AS Um, U2.Sigla AS Um2, A.Moltiplicatore AS Molt, A.Collo, TM.
dMagazzino, M.idArtVar, AM.Esistenza, AM.Disponibilita, AM.QtaImpegnata, AM.QtaOrdinata, TM.TipoSoggetto, TM.idSoggetto, ST.DataMovimento, MC.Codice, ST.Quantita, ST.Prezzo, ST.Sconti, M.idMagaRigMov
FROM MagaRigMov M
LEFT JOIN Articoli A ON A.idArticoli = M.idArticolo
LEFT JOIN UnMisura U ON U.idUnMisura = A.idUnMisura1
LEFT JOIN UnMisura U2 ON U2.idUnMisura = A.idUnMisura2
LEFT JOIN Iva I ON I.idIva = A.idIva
LEFT JOIN Settori S ON S.idSettori = A.idSettore
LEFT JOIN Fornitori F ON F.idFornitori = A.idFornitore
LEFT JOIN ArtCategorie C ON C.idArtCategorie = A.idArtCategoria
LEFT JOIN MagaTesMov TM ON TM.idMagaTesMov = M.idMagaTesMov
LEFT JOIN STORICO ST ON (ST.idSoggetto = TM.idSoggetto AND ST.TipoSoggetto = TM.TipoSoggetto AND ST.idArticolo = M.idArticolo)
LEFT JOIN MagaCausali MC ON MC.idMagaCausali = ST.idMagaCausale
LEFT JOIN ArtMaga AM ON IF(M.idArtVar IS NULL,(AM.idMagazzino = TM.idMagazzino AND AM.idArticolo = A.idArticoli),
(AM.idMagazzino = TM.idMagazzino AND AM.idArtVar = M.idArtVar))
This query is too slow.. but works..
You can't use an IF to make a conditional join. Because IF is not part of the SELECT syntax and even if it was (like CASE expressions) it wouldn't be allowed to be used like this. You can move the logic to the ON statement though:
LEFT JOIN ArtMaga G
ON (G.idMagazzino = V.idMagazzino AND G.idArticolo = M.idArticolo)
AND M.idArtVar IS NULL
OR (G.idMagazzino = V.idMagazzino AND G.idArticolo = M.idArticolo AND
G.idArtVar = M.idArtVar)
AND M.idArtVar IS NOT NULL
which can be simplified to:
LEFT JOIN ArtMaga G
ON (G.idMagazzino = V.idMagazzino AND G.idArticolo = M.idArticolo)
AND (M.idArtVar IS NULL OR G.idArtVar = M.idArtVar)
Also notice that you can't use equality to check if an expression is null.
M.idArtVar = null will never be true because NULL can never be equal to anything (not even to NULL). The way to check if an expression is null is with IS NULL.
Your second query, that words, is using the IF() function of MySQL and seems to be correct (although I see a difference in the code with the first query, the G.idArticolo = M.idArticolo condition has been removed from one part.)
Why a query is slow depends on many factors and using functions on the join conditions can be one of the many. Try the change I suggest above. If it still slow, you'll have to examine the execution plan and the available indexes on the tables.
Just put the condition in the on clause. If is not part of a SQL statement.
SELECT F.Codice AS "CodiceFornitore", F.RagioneSociale AS "RagioneSocialeFornitore",
A.ArticoloFornitore, C.Descrizione AS CatDes, S.Descrizione AS Settore, U.Sigla AS Um, U2.Sigla AS Um2, A.Moltiplicatore AS Molt, A.Collo, TM.
dMagazzino, M.idArtVar, AM.Esistenza, AM.Disponibilita, AM.QtaImpegnata, AM.QtaOrdinata, TM.TipoSoggetto, TM.idSoggetto, ST.DataMovimento, MC.Codice, ST.Quantita, ST.Prezzo, ST.Sconti, M.idMagaRigMov
FROM MagaRigMov M
LEFT JOIN Articoli A ON A.idArticoli = M.idArticolo
LEFT JOIN UnMisura U ON U.idUnMisura = A.idUnMisura1
LEFT JOIN UnMisura U2 ON U2.idUnMisura = A.idUnMisura2
LEFT JOIN Iva I ON I.idIva = A.idIva
LEFT JOIN Settori S ON S.idSettori = A.idSettore
LEFT JOIN Fornitori F ON F.idFornitori = A.idFornitore
LEFT JOIN ArtCategorie C ON C.idArtCategorie = A.idArtCategoria
LEFT JOIN MagaTesMov TM ON TM.idMagaTesMov = M.idMagaTesMov
LEFT JOIN STORICO ST ON (ST.idSoggetto = TM.idSoggetto AND ST.TipoSoggetto = TM.TipoSoggetto AND ST.idArticolo = M.idArticolo)
LEFT JOIN MagaCausali MC ON MC.idMagaCausali = ST.idMagaCausale
LEFT JOIN ArtMaga AM ON (AM.idMagazzino = TM.idMagazzino AND (m.idartVar is NULL and AM.idArtVar = M.idArtVar or AM.idArticolo = A.idArticoli))

Trying to add a subquery to a join query

I have a query like this
SELECT
tbl_products.*,
GROUP_CONCAT(tags.name)
FROM
tbl_page_collections_products,
(SELECT page_collection_name as name
FROM tbl_page_collections
LEFT JOIN tbl_pages ON tbl_page_collections.page_id = tbl_pages.page_id
WHERE tbl_pages.page_name LIKE '%friends%') tags
LEFT JOIN tbl_page_collections
ON tbl_page_collections.page_collection_id = tbl_page_collections_products.colID
LEFT JOIN tbl_pages
ON tbl_page_collections.page_id = tbl_pages.page_id
LEFT JOIN tbl_products
ON tbl_products.product_id = tbl_page_collections_products.product
WHERE
tbl_pages.page_name LIKE '%friends%'
The error I get is Unknown column 'tbl_page_collections_products.colID in on clause but I don't get that error when the subquery isn't there and that column exists in that table.
Is something conflicting?
tbl_page_collections_products is not in you subquery from clause. Maybe this is what you want:
SELECT
tbl_products.*,
GROUP_CONCAT(tags.name)
FROM
tbl_products,
(SELECT page_collection_name as name
FROM tbl_page_collections
,tbl_page_collections_products
LEFT JOIN tbl_pages ON tbl_page_collections.page_id = tbl_pages.page_id
WHERE tbl_pages.page_name LIKE '%friends%') tags
LEFT JOIN tbl_page_collections
ON tbl_page_collections.page_collection_id = tbl_page_collections_products.colID
LEFT JOIN tbl_pages
ON tbl_page_collections.page_id = tbl_pages.page_id
LEFT JOIN tbl_products
ON tbl_products.product_id = tbl_page_collections_products.product
WHERE
tbl_pages.page_name LIKE '%friends%'

i need to do an sql with if then else to join tables if the field is not null?

i need an sql stament that will give me something like this where if a field is null it doesn't do the join
SELECT AdminID,tblapartments.NameNo, tblgarages.GarageID, tblclients.Name FROM tbladmin,tblclients,tblgarages,tblapartments WHERE tblclients.ClientID =tbladmin.ClientID AND
IF (tbladmin.ApartmentID != null)
{
tblapartments.ApartmentID = tbladmin.ApartmentID
}
AND If(tbladmin.GarageID != Null)
{
tblgarges.GarageID = tbladmin.GarageID
}
Unless I'm missing something, this should just be an outer join.
SELECT
AdminID,
tblapartments.NameNo,
tblgarages.GarageID,
tblclients.Name
FROM
tbladmin INNER JOIN tblclients ON tbladmin.ClientID = tblclients.ClientID
LEFT OUTER JOIN tblgarages ON tbladmin.GarageID = tblgarages.GarageID
LEFT OUTER JOIN tblapartments ON tbladmin.ApartmentId = tblapartments.ApartmentID
You can use LEFT JOINs, when the joined column does not exist in the other table the result is a lot of NULL fields:
SELECT AdminID,tblapartments.NameNo, tblgarages.GarageID, tblclients.Name
FROM tbladmin
INNER JOIN tblclients
ON tbladmin.ClientID = tblclients.CliendID
LEFT JOIN tblgarages
ON tbladmin.GarageID = tblgarages.GarageID
LEFT JOIN tblapartments
ON tbladmin.ApartmentID = tblapartments.ApartmentID
I do not believe that this type of if logic is SQL standard. You could possibly implement it in a procedural SQL langauge like PL/SQL, plpgsql ... however to accomplish what you after i think a left join what you should look at.
SELECT AdminID,tblapartments.NameNo, tblgarages.GarageID, tblclients.Name
FROM tbladmin a
join tblclients b on b.ClientID = a.ClientID
left join tblapartments c on c.ApartmentID = a.ApartmentID
left join tblgarges d on d.GarageID = a.GarageID