how to full outer join with 3 tables in sql? - mysql

I have 3 tables :
table1 : "vw_dimserver" :[ServerKey,ServerNm,ServerCurrentAssignedToNm] for example : [1234,hasgapp0108,Aya]
table2 "vw_DimWorker" : [WorkerEmailNm, WorkerIdsid] . for example : [Aya, akhate] , [Genna,gshysh] , [mish,mishka] (it's like name and username)
table3 "vw_FactHardwareAssetContact" : [ServerKey,HardwareAssetWorkerKey, HardwareAssetContactTypeNm]. for example : [1234,Aya,support]
[1234,Genna,Customer]
[1234,Mish,patch] ( it's server key and the name of the contact and the contact type, if it's support or customer or patch)
I need the output to be in one row:
[ServerNm,WorkerIdsid of the ServerCurrentAssignedToNm, WorkerIdsid of the Customer, WorkerIdsid of the support]
[hasgapp0108,akhate,gshysh,mishka]
Now I need joins with the usernames table to get the username of each user.
I did it with Full outer join.
the code is :
SELECT
vw_dimserver.ServerNm as hostname ,
(vw_DimWorker1.WorkerIdsid) as username,
(vw_DimWorker2.WorkerIdsid) as [Primary Support Contact],
(vw_DimWorker3.WorkerIdsid) as [Primary Customer Contact]
from vw_dimserver
inner join vw_FactHardwareAssetContact on vw_dimserver.ServerKey = vw_FactHardwareAssetContact.HardwareAssetKey
inner join vw_DimWorker as vw_DimWorker1 on vw_DimWorker1.WorkerEmailNm = vw_dimserver.ServerCurrentAssignedToNm
full outer join vw_DimWorker as vw_DimWorker2 on CONVERT(varchar(11),vw_FactHardwareAssetContact.HardwareAssetWorkerKey ) = vw_DimWorker2.workerWWID and vw_FactHardwareAssetContact.HardwareAssetContactTypeNm = 'Support' and vw_FactHardwareAssetContact.HardwareAssetPrimaryInd = '1' and( vw_FactHardwareAssetContact.HardwareAssetWorkerKey is not NULL)
full outer join vw_DimWorker as vw_DimWorker3 on CONVERT(varchar(11),vw_FactHardwareAssetContact.HardwareAssetWorkerKey ) = vw_DimWorker3.workerWWID and vw_FactHardwareAssetContact.HardwareAssetContactTypeNm = 'Customer' and vw_FactHardwareAssetContact.HardwareAssetPrimaryInd = '1' and( vw_FactHardwareAssetContact.HardwareAssetWorkerKey is not NULL)
where vw_dimserver.ServerNm ='hasgapp0108' and (vw_DimWorker2.workerWWID is not null or vw_DimWorker3.workerWWID is not null ) and ( ServerCurrentSubStatusCd != 'duplicate_error' or ServerCurrentSubStatusCd is NULL )
The output is two rows:
[hostname username Support Customer ]
[hasgapp0108 akhate NULL gshysh],
[hasgapp0108 akhate akhate NULL]
and I need it to be one row :
[hostname username Support Customer]
[hasgapp0108 akhate akhate gshysh]
My manager didn't accept the solutaion :
select max(username1),max(username2)...
I need to do it with joins.

Try this with inner join and group_concat:
SELECT vw_dimserver.ServerNm as hostname , group_concat(vw_DimWorker1.WorkerIdsid) as username, group_concat(vw_DimWorker2.WorkerIdsid) as [Primary Support Contact], group_concat(vw_DimWorker3.WorkerIdsid) as [Primary Customer Contact]
from vw_dimserver
inner join vw_FactHardwareAssetContact on vw_dimserver.ServerKey = vw_FactHardwareAssetContact.HardwareAssetKey
inner join vw_DimWorker as vw_DimWorker1 on vw_DimWorker1.WorkerEmailNm = vw_dimserver.ServerCurrentAssignedToNm
full outer join vw_DimWorker as vw_DimWorker2 on CONVERT(varchar(11),vw_FactHardwareAssetContact.HardwareAssetWorkerKey ) = vw_DimWorker2.workerWWID and vw_FactHardwareAssetContact.HardwareAssetContactTypeNm = 'Support' and vw_FactHardwareAssetContact.HardwareAssetPrimaryInd = '1' and( vw_FactHardwareAssetContact.HardwareAssetWorkerKey is not NULL)
full outer join vw_DimWorker as vw_DimWorker3 on CONVERT(varchar(11),vw_FactHardwareAssetContact.HardwareAssetWorkerKey ) = vw_DimWorker3.workerWWID and vw_FactHardwareAssetContact.HardwareAssetContactTypeNm = 'Customer' and vw_FactHardwareAssetContact.HardwareAssetPrimaryInd = '1' and( vw_FactHardwareAssetContact.HardwareAssetWorkerKey is not NULL)
where vw_dimserver.ServerNm ='hasgapp0108' and (vw_DimWorker2.workerWWID is not null or vw_DimWorker3.worker
group by vw_dimserver.ServerNm

You could use an inner join if you need only matching result
SELECT
s.ServerKey,
s.ServerNm,
group_concat(w.WorkerIdsid)
FROM vw_dimserver s
INNER JOIN vw_FactHardwareAssetContact c
ON s.ServerKey = c.ServerKey
INNER JOIN vw_DimWorker w
ON c.HardwareAssetWorkerKey = w.WorkerEmailNm
GROUP BY s.ServerKey,
s.ServerNm
OR You could use left join if there are not all matching
SELECT
s.ServerKey,
s.ServerNm,
group_concat(w.WorkerIdsid)
FROM vw_dimserver s
LEFT JOIN vw_FactHardwareAssetContact c
ON s.ServerKey = c.ServerKey
LEFT JOIN vw_DimWorker w
ON c.HardwareAssetWorkerKey = w.WorkerEmailNm
GROUP BY s.ServerKey,
s.ServerNm

SELECT vw_dimserver.ServerNm as hostname , (vw_DimWorker1.WorkerIdsid) as username, (vw_DimWorker2.WorkerIdsid) as [Primary Support Contact], (vw_DimWorker3.WorkerIdsid) as [Primary Customer Contact]
from vw_dimserver
full outer join vw_FactHardwareAssetContact as vw_FactHardwareAssetContact1
on (vw_dimserver.ServerKey = vw_FactHardwareAssetContact1.HardwareAssetKey and vw_FactHardwareAssetContact1.HardwareAssetContactTypeNm = 'Support' and vw_FactHardwareAssetContact1.HardwareAssetPrimaryInd = '1' )
full outer join vw_DimWorker as vw_DimWorker1 on CONVERT(varchar(11),vw_FactHardwareAssetContact1.HardwareAssetWorkerKey ) = vw_DimWorker1.workerWWID
full outer join vw_DimWorker as assings on assings.WorkerEmailNm = vw_dimserver.ServerCurrentAssignedToNm
full outer join vw_FactHardwareAssetContact as vw_FactHardwareAssetContact2 on (vw_dimserver.ServerKey = vw_FactHardwareAssetContact2.HardwareAssetKey and vw_FactHardwareAssetContact2.HardwareAssetContactTypeNm = 'Customer' and vw_FactHardwareAssetContact2.HardwareAssetPrimaryInd = '1' )
full outer join vw_DimWorker as vw_DimWorker2 on CONVERT(varchar(11),vw_FactHardwareAssetContact2.HardwareAssetWorkerKey ) = vw_DimWorker2.workerWWID
full OUTER join vw_FactHardwareAssetContact as vw_FactHardwareAssetContact11 on (vw_dimserver.ServerKey = vw_FactHardwareAssetContact11.HardwareAssetKey and vw_FactHardwareAssetContact11.HardwareAssetContactTypeNm = 'Support' and vw_FactHardwareAssetContact11.HardwareAssetPrimaryInd = '0' )
full outer join vw_DimWorker as vw_DimWorker11 on CONVERT(varchar(11),vw_FactHardwareAssetContact11.HardwareAssetWorkerKey ) = vw_DimWorker11.workerWWID
full OUTER join vw_FactHardwareAssetContact as vw_FactHardwareAssetContact22 on (vw_dimserver.ServerKey = vw_FactHardwareAssetContact22.HardwareAssetKey and vw_FactHardwareAssetContact22.HardwareAssetContactTypeNm = 'Customer' and vw_FactHardwareAssetContact11.HardwareAssetPrimaryInd = '0' )
full outer join vw_DimWorker as vw_DimWorker22 on CONVERT(varchar(11),vw_FactHardwareAssetContact22.HardwareAssetWorkerKey ) = vw_DimWorker22.workerWWID

Related

how understand the relation between parent query and subquery in mysql?

Someone please explain the difference between parent query and sub query? How do I understand?
e.g:
SELECT
ra.ID id,
ra.ACCOUNT_ID accountId,
ef.REAL_NAME realName,
a.MOBILE mobile,
sps.`NAME` siteName,
ef.CREATE_TIME createTime,
a.`STATUS` status,
ra.`STATUS` siteStatus,
(
SELECT
aif.APPROVER_NAME
FROM
audit_info aif
WHERE
aif.TARGET_ID = a.ID AND af.AUDIT_TYPE=2
AND aif.CREATE_TIME = (
SELECT
MAX(af.CREATE_TIME)
FROM
audit_info af
WHERE
af.TARGET_ID = a.ID AND af.AUDIT_TYPE=2
)
) AS approverName
FROM
account a
INNER JOIN site_relation_account ra ON ra.ACCOUNT_ID = a.ID
INNER JOIN account_ext ef ON ra.ACCOUNT_ID = ef.ACCOUNT_ID
INNER JOIN service_provider_site sps ON sps.ID = ra.SITE_ID
LEFT JOIN audit_info af ON af.TARGET_ID = ef.ACCOUNT_ID
WHERE ra.ACCOUNT_TYPE = 2

mysql using outside alias to 2 level deep subquery

I'm currently stuck here and don't know what to do next since I can't use the tv_main alias into the 2 level deep subquery. Here's my code (I commented the part that have a problem). Any help will be appreciated. Thanks.
SELECT tv_main.id,
tv_main.vesselName,
(
SELECT SUM(t_statCtr.status = 'EX CREW')
FROM
(
(
SELECT tpi_stat.id,
tvv.vesselName,
lastname,
firstname,
middlename,
IF(tpi_stat.returningCrew = 1, 'NEW HIRE',
IF(COUNT(tc_ctr.personnel_id) > 1, 'EX CREW', 'NEW HIRE')
)
AS status
FROM tbl_contracts AS tc_stat
LEFT JOIN tbl_personnel_info AS tpi_stat
ON tpi_stat.id = tc_stat.personnel_id
LEFT JOIN tbl_contracts AS tc_ctr
ON tpi_stat.id = tc_ctr.personnel_id
LEFT JOIN tbl_vessels AS tvv
ON tvv.id = tpi_stat.lastJoinedVsl
WHERE
tpi_stat.emp_status = 'ON-BOARD'
AND tc_stat.status = 'ACTIVE'
AND tvv.id = tv_main.id --This line have an error, (Unknown Column tv_main.id in where clause)
GROUP BY tc_stat.personnel_id
) AS t_statCtr
)
) AS ex_crew,
NULL AS new_hire
FROM tbl_vessels AS tv_main -- I need this one to use inside the subquery
LEFT JOIN tbl_personnel_info AS tpi
ON tv_main.id = tpi.lastJoinedVsl
LEFT JOIN tbl_contracts AS tc
ON tpi.id = tc.personnel_id
WHERE
tpi_stat.emp_status = 'ON-BOARD'
AND tc_stat.status = 'ACTIVE'
GROUP BY tv_main.vesselName
I finally solve it. I didn't know that mysql only allow correlation of 1 deep level.
SELECT tv_main.vesselName,
SUM(t_dummy.statusx = 'EX CREW') AS ex_crew,
SUM(t_dummy.statusx = 'NEW HIRE') AS new_hire
FROM tbl_vessels AS tv_main
LEFT JOIN tbl_personnel_info AS tpi_main
ON tpi_main.lastJoinedVsl = tv_main.id
LEFT JOIN tbl_contracts AS tc_main
ON tc_main.personnel_id = tpi_main.id
LEFT JOIN
(
SELECT tvv.id,
tpi_stat.id AS tpiid,
IF(tpi_stat.returningCrew = 1, 'NEW HIRE',
IF(COUNT(tc_ctr.personnel_id) > 1, 'EX CREW', 'NEW HIRE')
)
AS statusx
FROM tbl_contracts AS tc_stat
LEFT JOIN tbl_personnel_info AS tpi_stat
ON tpi_stat.id = tc_stat.personnel_id
LEFT JOIN tbl_contracts AS tc_ctr
ON tpi_stat.id = tc_ctr.personnel_id
LEFT JOIN tbl_vessels AS tvv
ON tvv.id = tpi_stat.lastJoinedVsl
GROUP BY tc_stat.personnel_id
) AS t_dummy
ON tpi_main.id = t_dummy.tpiid
WHERE
tpi_main.emp_status = 'ON-BOARD'
AND tc_main.status = 'ACTIVE'
AND t_dummy.id = tv_main.id
GROUP BY tv_main.vesselName;

Like best performance in nested query

I have a principal requet with 2 requets in. I have a problem in my second nested query, I have a condition on id and if I made my request id = 10 takes a long time to execute, so if I replace it by id LIKE 10 my request execute in one second.
Here the request:
SELECT SQL_NO_CACHE contact_groupe.id_contact_groupe
FROM toto.contact_groupe
LEFT JOIN toto.`contact` AS `contact`
ON ((toto.contact_groupe.id_contact_groupe = toto.contact.id_contact_groupe))
LEFT JOIN toto.`project` AS `project`
ON ((toto.contact_groupe.id_contact_groupe = toto.project.id_contact_groupe)
AND ( toto.project.id_project
IN (
SELECT MAX(toto.project.id_project)
FROM toto.project
WHERE ( toto.contact_groupe.id_contact_groupe = toto.project.id_contact_groupe )
) ))
LEFT JOIN toto.`phase` AS `phase`
ON ((project.id_phase = toto.phase.id_phase))
LEFT JOIN sql_base.`user` AS `user_suivi`
ON ((toto.contact_groupe.id_user_suivi = user_suivi.id_user))
WHERE ( en_attente = '0' AND contact_groupe.id_contact_groupe
IN (
SELECT DISTINCT(contact_groupe.id_contact_groupe)
FROM toto.contact_groupe
LEFT JOIN toto.`contact` AS `contact`
ON ((toto.contact_groupe.id_contact_groupe = toto.contact.id_contact_groupe)
LEFT JOIN toto.`source_contact_groupe` AS `source_contact_groupe`
ON ((toto.contact_groupe.id_contact_groupe = toto.source_contact_groupe.id_contact_groupe))
LEFT JOIN toto.`project` AS `project`
ON ((toto.contact_groupe.id_contact_groupe = toto.project.id_contact_groupe))
LEFT JOIN toto.`remarque` AS `remarque`
ON ((toto.contact_groupe.id_contact_groupe = toto.remarque.id_contact_groupe))
LEFT JOIN toto.`project_type_construction_options` AS `project_type_construction_options`
ON ((project.id_project = toto.project_type_construction_options.id_project))
LEFT JOIN toto.`project_concurrent` AS `project_concurrent`
ON ((project.id_project = toto.project_concurrent.id_project))
LEFT JOIN toto.`telephone` AS `telephone`
ON ((contact.id_contact = toto.telephone.id_contact))
WHERE ( en_attente = '0' AND ( toto.project.id_project = '10' ) AND toto.contact_groupe.id_entreprise = '2' )
)
AND toto.contact_groupe.id_entreprise = '2' )
ORDER BY toto.contact_groupe.id_contact_groupe ASC
the line is the following problem toto.project.id_project = '10' and I don't understand why the time to execute request is so different between = and LIKE
Let's start with your subquery. Those 17 lines that you've written are functionally identical to this, so why not use this instead?
SELECT DISTINCT g.id_contact_groupe
FROM contact_groupe g
JOIN project p
ON p.id_contact_groupe = g.id_contact_groupe
WHERE g.en_attente = 0
AND p.id_project = 10
AND g.id_entreprise = 2

How do I left join only if previous left join didn't find anything

It shouldn't join on tbi2 if tbi1 finds a result, but it retrieving results from both tables.
The idea of this is to join on the item table but if there isn't an exact match, fallback to joining on '*'
(This is the same SQL statement as a previous question, but a different attempt... again.)
SELECT
COALESCE(tbi1.id,tbi2.id,tbi3.id,tbi4.id,tbi5.id,tbi6.id) AS id
,COALESCE(tbi1.cost,tbi2.cost,tbi3.cost,tbi4.cost,tbi5.cost,tbi6.cost) AS cost
,COALESCE(tbi1.price,tbi2.price,tbi3.price,tbi4.price,tbi5.price,tbi6.price) AS price
,COALESCE(tbi1.itemNumber,tbi2.itemNumber,tbi3.itemNumber,tbi4.itemNumber,tbi5.itemNumber,tbi6.itemNumber) AS itemNumber
,COUNT(COALESCE(tbi1.id,tbi2.id,tbi3.id,tbi4.id,tbi5.id,tbi6.id)) AS quantityToAdd
,tbl_equipment.id AS equipId
,tbl_equipment.partNum
,tbl_equipment.nolinks
,tbl_addedItemCustomerPrices.customerprice AS specialPrice
,tbl_testTypes.isInspt
,tbl_testTypes.isRecharge
,tbl_testTypes.isRecharagable
,tbl_tests.nextDate AS theNextDate
FROM
tbl_tests
INNER JOIN tbl_equipment ON tbl_equipment.id = tbl_tests.equipmentId
INNER JOIN tbl_model ON tbl_model.id = tbl_equipment.model
INNER JOIN tbl_testTypes ON tbl_testTypes.id = tbl_tests.testTypeId
LEFT JOIN tbl_items AS tbi1 ON tbi1.size = tbl_model.size AND tbi1.service = tbl_testTypes.name
LEFT JOIN tbl_items AS tbi2 ON tbi2.size = '*' AND tbi2.service = tbl_testTypes.name AND tbi1.id IS NULL
LEFT JOIN tbl_items AS tbi3 ON tbi3.type = tbl_model.type AND tbi3.service = tbl_testTypes.name AND tbi2.id IS NULL
LEFT JOIN tbl_items AS tbi4 ON tbi4.type = '*' AND tbi4.service = tbl_testTypes.name AND tbi3.id IS NULL
LEFT JOIN tbl_items AS tbi5 ON tbi5.category = tbl_model.category AND tbi5.service = tbl_testTypes.name AND tbi4.id IS NULL
LEFT JOIN tbl_items AS tbi6 ON tbi6.category = '*' AND tbi6.service = tbl_testTypes.name AND tbi5.id IS NULL
LEFT JOIN tbl_addedItemCustomerPrices ON COALESCE(tbi1.id,tbi2.id,tbi3.id,tbi4.id,tbi5.id,tbi6.id) = tbl_addedItemCustomerPrices.itemId AND tbl_addedItemCustomerPrices.customerid = $currentSite
WHERE
((nextDate >= '$startDate' AND nextDate <= '$endDate' ) OR tbl_testTypes.isRecharge = 'true')
{$monthEndQuery}
AND tbl_equipment.site = $currentSite
GROUP BY COALESCE(tbi1.id,tbi2.id,tbi3.id,tbi4.id,tbi5.id,tbi6.id)
ORDER BY tbl_equipment.id, isRecharagable DESC

MySql query: sometimes getting an empty result set

I have this query:
SELECT CONCAT(f.name, ' ', f.parent_names) AS FullName,
stts.name AS 'Status',
u.name AS Unit,
city.name AS City,
hus.mobile1 AS HusbandPhone,
wife.mobile1 AS WifePhone,
f.phone AS HomePhone,
f.contact_initiation_date AS InitDate,
fh.created_at AS StatusChangeDate,
cmt.created_at AS CommentDate,
cmt.comment AS LastComment,
f.reconnection_date AS ReconnectionDate,
(
SELECT GROUP_CONCAT(t.name)
FROM taggings tgs JOIN tags t
ON tgs.tag_id = t.id
WHERE tgs.taggable_type = 'family' AND
tgs.taggable_id = f.id
) AS HandlingStatus
FROM families f
JOIN categories stts ON f.family_status_cat_id = stts.id
JOIN units u ON f.unit_id = u.id
JOIN categories city ON f.main_city_cat_id = city.id
JOIN contacts hus ON f.husband_id = hus.id
JOIN contacts wife ON f.wife_id = wife.id
JOIN comments cmt ON f.id = cmt.commentable_id AND
cmt.created_at = (SELECT MAX(created_at) FROM comments WHERE commentable_id = f.id)
JOIN family_histories fh ON f.id = fh.family_id AND
fh.created_at = (SELECT MAX(created_at) FROM family_histories WHERE family_id = f.id AND family_history_cat_id = 1422) AND
fh.family_history_cat_id = 1422
WHERE f.id = 12212
The problem is with the second SELECT (the column - HandlingStatus).
I don't understand but when the column has results (tested as a stand alone query) - I get an empty result set, and when there are no results - I get a result.
Why?