Query to get all siblings - sql

I have table like that:
ID NAME SURNAME MotherID FatherID
0 JJ smi NULL NULL
1 ja rly NULL NUL
2 ak smi 0 1
3 ol smi 0 1
4 oa woo 2 3
5 oe boo 2 3
etc.
I need query that with specific parameter as NAME and surname will return me all siblings of a person.
Expected output
NAME SURNAME FATHERNAME FATHERSURNAME MOTHERNAME MOTHERSURNAME
AK SMI JA RLY JJ SMI
OL SMI JA RLY JJ SMI
I tried
SELECT
a.name,
a.surname
FROM PEOPLE a, PEOPLE b
WHERE (b.name = 'ak' AND b.surname ='smi' AND
(b.motherID = a.ID OR b.fatherid = ID))

You can use a SUB QUERY to achieve this.
Table Creation:
DECLARE #T TABLE(
ID INT,
NAME VARCHAR(MAX),
SURNAME VARCHAR(MAX),
MOTHERID INT,
FATHERID INT)
Table Insertion:
Insert into #t Values(0,'JJ','smi',NULL,NULL)
Insert into #t Values(1,'ja','rly',NULL,NULl)
Insert into #t Values(2,'ak','smi',0,1)
Insert into #t Values(3,'ol','smi',0,1)
Insert into #t Values(4,'oa','woo',2,3)
Insert into #t Values(5,'oe','boo',2,3)
Query:
SELECT S.NAME AS NAME,S.SURNAME AS SURNAME,S.FATHER_NAME ,S.FATHER_SURNAME,M.NAME AS
MOTHER_NAME,M.SURNAME AS MOTHER_SURNAME
FROM #T M INNER JOIN(
SELECT T2.NAME AS NAME,T2.SURNAME AS SURNAME,T1.NAME AS FATHER_NAME,T1.SURNAME AS
FATHER_SURNAME,T2.MOTHERID
FROM #T T1
INNER JOIN #T T2 ON T1.ID=T2.FATHERID
WHERE T2.NAME IN ('AK','OL'))S ON M.ID=S.MOTHERID
Output:
Also ,add the WHERE clause based on your parameter requirement.

Here is one way you can get it. From here you can explore a few other options!
CREATE PROC GetSiblings
(
#GivenName AS VARCHAR(100),
#SurName AS VARCHAR(100)
)
AS
BEGIN
SET NOCOUNT ON;
SELECT
A.GivenName,
A.SurName,
F.GivenName AS FatherGivenName,
F.SurName AS FatherSurName,
M.GivenName AS MotherGivenName,
M.SurName AS MotherSurName,
FROM PEOPLE AS P INNER JOIN PEOPLE AS F ON P.FatherID = F.ID
INNER JOIN PEOPLE AS M ON P.MotherID = M.ID
WHERE P.GivenName = #GivenName AND P.SurName = #SurName
UNION --By father
SELECT
A.GivenName,
A.SurName,
F.GivenName AS FatherGivenName,
F.SurName AS FatherSurName,
M.GivenName AS MotherGivenName,
M.SurName AS MotherSurName,
FROM PEOPLE AS P INNER JOIN PEOPLE AS F ON P.FatherID = F.ID
INNER JOIN PEOPLE AS M ON P.MotherID = M.ID
WHERE P.FatherID IN (SELECT DISTINCT FatherID FROM PEOPLE WHERE GivenName = #GivenName AND SurName = #SurName)
UNION --By mother
SELECT
A.GivenName,
A.SurName,
F.GivenName AS FatherGivenName,
F.SurName AS FatherSurName,
M.GivenName AS MotherGivenName,
M.SurName AS MotherSurName,
FROM PEOPLE AS P INNER JOIN PEOPLE AS F ON P.FatherID = F.ID
INNER JOIN PEOPLE AS M ON P.MotherID = M.ID
WHERE P.MotherID IN (SELECT DISTINCT MotherID FROM PEOPLE WHERE GivenName = #GivenName AND SurName = #SurName);
END;

Related

SELECT common entities only based on different corresponding entities

3 Tables
Client -
CID Name
1 Ana
2 Bana
3 Cana
ClientProgram (Bridge Table) -
CID PID
1 4
1 5
1 8
2 10
Program -
PID Program
4 X
5 Y
8 Z
10 G
Desired Output:
Name Program
Ana X
Ana Y
I want to extract only those Clients which are common/exist in different Programs I choose (say X and Y in this case)
Query attempt:
SELECT
C.Name
,P.Program
FROM ClientProgram CP
INNER JOIN Client C
ON CP.CID=C.CID
INNER JOIN Program P
ON CP.PID=P.PID
INNER JOIN ClientProgram CP1
ON CP.CID=CP1.CID
WHERE P.Program = 'X' OR P.Program = 'Y'
AND CP.CID = CP1.CID
This however doesn't pulls in all clients and not only those which exist in multiple programs.
;WITH cte AS (
SELECT
c.Name
,p.Program
,COUNT(*) OVER (PARTITION BY c.CID) as ProgramCount
FROM
Program p
INNER JOIN ClientProgram cp
ON p.PID = cp.PID
INNER JOIN Client c
On cp.CID = c.CID
WHERE
p.Program IN ('X','Y')
)
SELECT Name, Program
FROM
cte
WHERE
ProgramCount > 1
The use of COUNT(*) over will be a problem if PID is not unique in Programs or if the combination of CID to PID in ClientProgram is not unique. However I would assume uniqueness based on what I see.
If not you can go a route like this:
;WITH cte AS (
SELECT
cp.CID
FROM
Program p
INNER JOIN ClientProgram cp
ON p.PID = cp.PID
WHERE
p.Program IN ('X','Y')
GROUP BY
cp.CID
HAVING
COUNT(DISTINCT p.PID) > 1
)
SELECT
c.Name
,p.Program
FROM
cte t
INNER JOIN Client c
ON t.CID = c.CID
INNER JOIN ClientProgram cp
ON t.CID = cp.CID
INNER JOIN Program p
ON cp.PID = p.PID
AND p.Program IN ('X','Y')
This is kind of a round about way of doing it. Probably a better way but this will do it. I through in scripts for temp table in case someone else wants to improve. Could do a temp table for example instead of CTE.
create table #client(cid int,name varchar(20))
create table #clientprogram (cid int, pid int)
create table #program( pid int, program varchar(20))
insert into #client
values(1,'Ana')
,(2,'Bana')
,(3,'Cana')
insert into #clientprogram
values (1,4)
,(1,5)
,(1,8)
,(2,10)
,(2,4)
insert into #program
values (4,'x')
,(5,'y')
,(8,'z')
,(10,'g')
WITH CHECKPLEASE AS(
Select c.Name,ISNULL(p.Program,p2.PRogram) Program
from #client c
inner join #clientprogram cp
on c.CID = cp.CID
left join #program p
on cp.PID = p.PID
and p.PRogram = 'X'
left join #program p2
on cp.PID = p2.PID
and p2.Program = 'Y'
where ISNULL(p.Program,p2.PRogram) is not null
)
Select *
From CHECKPLEASE
where Name in (
SELECT Name
From CHECKPLEASE
group by Name
having COUNT(*) > 1)

Understanding nested select queries

Have a question in regards to what was a select into query that I am changing into an insert into query with a select and I just wanted somebody to help me understand the query and know why the only fields in the select it wants are only certain fields.
Ok so below is a create table statement I have written for the temp tables '#Infants' and '#MobileBookings'.
create table #MobileBookings
(
Reference nvarchar(50),
CreatedDate datetime,
FirstName nvarchar(50),
Surname nvarchar(50),
PersonTypeId int,
PackageId int,
PersonId int,
ProductId int,
StatusId smallint
)
create table #Infants
(
Reference nvarchar(50),
CreatedDate datetime,
FirstName nvarchar(50),
Surname nvarchar(50),
PersonTypeId int,
ProductPersonId int,
StatusId smallint,
FlightNumber nvarchar(50),
DepartureDateTime datetime,
SectorName nvarchar(50),
BoundID varchar(8)
)
Now what I have in the existing code (that I didn't write but trying to manipulate by including insert into instead of what previously was select into to remove certain warnings.
insert into #Infants (
Reference, CreatedDate, FirstName, Surname,
PersonTypeId, ProductPersonId, StatusId, FlightNumber,
DepartureDateTime, SectorName, BoundID
)
select * from
(
select
x.Reference, x.CreatedDate, x.FirstName, x.Surname,
x.PersonTypeId, pp.ProductPersonId, pp.StatusId as 'ProductPersonStatusID', null as 'DependantPPID',
fl.FlightNumber,
fl.DepartureDateTime, fs.SectorName, iif(fr.BoundID=0,'OutBound','InBound') as 'FlightBound'
from #MobileBookings as x
inner join Reservations_Live.dbo.ProductPerson as pp with (nolock) on pp.ProductID = x.ProductId and pp.PersonId = x.PersonId
inner join Reservations_Live.dbo.FlightReservation as fr with (nolock) on fr.ProductId = x.ProductId
inner join Reservations_Live.dbo.Flight as fl with (nolock) on fl.FlightId = fr.FlightId
inner join Reservations_Live.dbo.FlightSector as fs with (nolock) on fs.FlightSectorId = fl.FlightSectorId
INNER join
(
select x.PackageId as 'PKID', frp.DependantProductPersonId as 'DepPPID', frp.ProductPersonID as 'CarerPPID',
pp.StatusId as 'CarerPPST'
from #MobileBookings as x
inner join Reservations_Live.dbo.ProductPerson as pp with (nolock) on pp.ProductID = x.ProductId and pp.PersonId = x.PersonId
inner join Reservations_Live.dbo.FlightReservationPassenger as frp with (nolock) on frp.ProductPersonID = pp.ProductPersonId
where x.PersonTypeId = 1
and pp.StatusId = 3
and frp.DependantProductPersonId is not null
)
as car on car.PKID = x.PackageId and car.DepPPID = pp.ProductPersonId
where x.StatusId < 7
and x.PersonTypeId = 3
and pp.StatusId = 2
and fl.FlightStatusId < 3
and fl.DepartureDateTime > GETUTCDATE()
) as inf;
set #ActualRowCount = ##rowcount;
Ok so in visual studio, if I hover over the * in the select statement, it displays a hover box that shows the only fields it requires to select:
Reference (nvarchar, null),
CreatedDate (datetime, null),
FirstName (nvarchar, null),
Surname (nvarchar, null),
PersonTypeId (int, null),
ProductPersonStatusID(, null),
DependantPPID(void, not null),
FlightBound (, null)
I'm assuming I need to change my create table and insert into to only include these relevant fields above but what I want to know is how come it only wants to select these fields and not include any other relevant fields?
Also in regards to the ProductPersonStatusID and DependantPPID which is based on the 'StatusID', are they actually displayed as two columns in the final output, meaning the create table will need to include both these columns and they both also need to be included in the insert into? StatusId is an int so if this is the case, I'm assuming 'ProductPersonStatusID' should be set as an int but DependantPPID should be set as a null in the CREATE statement?
UPDATE:
Hopefully I'm in the right section but included the subquery for inf as stated in the comment:
update pp
set pp.StatusId = 3
output 'ProductPerson', 'ProductPersonId', inserted.ProductPersonId,
Core.updXMLFragment('StatusId',inserted.StatusId,deleted.StatusId)
into #OutputList
from Reservations_Live.dbo.ProductPerson as pp
inner join #Infants as inf on inf.ProductPersonId = pp.ProductPersonId;
set #UpdateRowCount = ##Rowcount;
Just to make sure, I have changed the create table and the insert into statement to the follow, which I hope is correct:
create table #Infants
(
Reference nvarchar(50),
CreatedDate datetime,
FirstName nvarchar(50),
Surname nvarchar(50),
PersonTypeId int,
ProductPersonStatusID int,
DependantPPID int,
FlightBound varchar(8)
);
--
insert into #Infants (Reference, CreatedDate, FirstName, Surname, PersonTypeId, ProductPersonStatusID, DependantPPID, FlightBound)
select * from...
I suggest you remove the select * altogether. This is bad practice. There is rarely a good reason to use SELECT * As it was you had a couple of fields mismatched.
Note how the order of fields in the INSERT needs to match the order of fields in the SELECT. That's why I like to spread them across a few lines so I can match them up.
Also WITH (NOLOCK) is not magic go fast switch but that's for another post....
insert into #Infants (
Reference, CreatedDate,
FirstName, Surname,
PersonTypeId, ProductPersonId,
StatusId, FlightNumber,
DepartureDateTime, SectorName,
BoundID
)
select
x.Reference, x.CreatedDate,
x.FirstName, x.Surname,
x.PersonTypeId, pp.ProductPersonId,
pp.StatusId as [ProductPersonStatusID], fl.FlightNumber,
fl.DepartureDateTime, fs.SectorName,
iif(fr.BoundID=0,'OutBound','InBound') as [FlightBound]
from #MobileBookings as x
inner join Reservations_Live.dbo.ProductPerson as pp with (nolock) on pp.ProductID = x.ProductId and pp.PersonId = x.PersonId
inner join Reservations_Live.dbo.FlightReservation as fr with (nolock) on fr.ProductId = x.ProductId
inner join Reservations_Live.dbo.Flight as fl with (nolock) on fl.FlightId = fr.FlightId
inner join Reservations_Live.dbo.FlightSector as fs with (nolock) on fs.FlightSectorId = fl.FlightSectorId
INNER join
(
select x.PackageId as 'PKID', frp.DependantProductPersonId as 'DepPPID', frp.ProductPersonID as 'CarerPPID',
pp.StatusId as 'CarerPPST'
from #MobileBookings as x
inner join Reservations_Live.dbo.ProductPerson as pp with (nolock) on pp.ProductID = x.ProductId and pp.PersonId = x.PersonId
inner join Reservations_Live.dbo.FlightReservationPassenger as frp with (nolock) on frp.ProductPersonID = pp.ProductPersonId
where x.PersonTypeId = 1
and pp.StatusId = 3
and frp.DependantProductPersonId is not null
)
as car on car.PKID = x.PackageId and car.DepPPID = pp.ProductPersonId
where x.StatusId < 7
and x.PersonTypeId = 3
and pp.StatusId = 2
and fl.FlightStatusId < 3
and fl.DepartureDateTime > GETUTCDATE()

Selecting Distinct Fields From Joined Rows

I have a table ANIMAL and another table CALF_PARENT
Design of ANIMAL table is:
ID PK IDENTITY(1,1),
TagNo varchar(30)
and other columns...
Design of CALF_PARENT is:
ID PK IDENTITY(1,1),
Parent int (FK from Animal),
IsMother varchar(1)
I am writing following query to join two tables:
SELECT a.[TagNo]
,a.ID
,a2.TagNo
,isnull(cp.Parent,0)
,a3.TagNo
,isnull(cp.Parent,0)
FROM [dbo].[ANIMAL] a
LEFT JOIN [CALF_PARENT] cp
ON a.ID = cp.Calf
LEFT JOIN ANIMAL a2
ON a2.ID = cp.Parent AND cp.IsMother = 'Y' AND a2.ID IS NOT NULL
LEFT JOIN ANIMAL a3
ON a3.ID = cp.Parent AND cp.IsMother = 'N' AND a3.ID IS NOT NULL
Its returning me record like this:
Tag, CalfID, FatherTagNo, FatherID, MotherTagNo, MotherID
FA-56 21 AB-670 3
FA-56 21 CW-59 7
I want it to return me single row like this:
Tag, CalfID, FatherTagNo, FatherID, MotherTagNo, MotherID
FA-56 21 AB-670 3 CW-59 7
What would be the simplest way to implement it.
SELECT DISTINCT a.[TagNo] As Tag
,a.ID As CalfID
,MAX(a2.TagNo) As FatherTagNo
,MAX(isnull(cp.Parent,0)) As FatherID
,MAX(a3.TagNo) As MotherTagNo
,MAX(isnull(cp.Parent,0))As MotherID
FROM [dbo].[ANIMAL] a
LEFT JOIN [CALF_PARENT] cp
ON a.ID = cp.Calf
LEFT JOIN ANIMAL a2
ON a2.ID = cp.Parent AND cp.IsMother = 'Y' AND a2.ID IS NOT NULL
LEFT JOIN ANIMAL a3
ON a3.ID = cp.Parent AND cp.IsMother = 'N' AND a3.ID IS NOT NULL
GROUP BY a.[TagNo] ,a.ID
and with example
declare #t table (id varchar(10),cal int,father varchar(10),fatherid int,mother varchar(20),motherid int)
insert into #t(id,cal,father,fatherid,mother,motherid) values ('FA-56',21,'AB-670',3,NULL,NULL)
insert into #t(id,cal ,father,fatherid,mother,motherid) values ('FA-56',21,null,null, 'CW-59',21)
select distinct id As i,cal,MAX(father),MAX(fatherid),MAX(mother),MAX(motherid) from #t
group by id,cal
try this:
SELECT a.*, cpmd.*, cpfd.*
FROM dbo.ANIMAL a
LEFT JOIN CALF_PARENT cpm ON a.ID = cpm.Calf AND cpm.IsMother = 'Y'
LEFT JOIN ANIMAL cpmd ON cpmd.ID = cpm.Parent
LEFT JOIN CALF_PARENT cpf ON a.ID = cpf.Calf AND cpf.IsMother = 'N'
LEFT JOIN ANIMAL cpfd ON cpfd.ID = cpf.Parent
and your life would be easier if your calf_parent table would consist of 3 columns:
Animal_ID (PK), Father_ID, Mother_ID

Joining Two Temp Tables

I would like to join two temp tables into one big temp table. I want all of the records from my first temp table and want the records from my second temp table ONLY if the ProductID doesn't exist in my first temp table.
First temp table:
--define temporary table
declare #tmp table (
ManagerID int null,
ManagerName varchar(250),
ProductID int null,
ProductName varchar(250),
RFIFixedIncomeAttributionID int null,
Value decimal(8,4) null,
Name varchar(250),
Sector varchar(250)
)
--populate temp table
insert into #tmp
select
m.ManagerID, m.ManagerName, p.ID as 'ProductID', p.ProductName, sa.RFIFixedIncomeAttributionID, sa.Value, sc.Name,
case when gm.GeographicMandateID = 2 and s1.SubType1ID = 10 and s2.SubType2ID = 39 then 'Core'
when gm.GeographicMandateID = 2 and s1.SubType1ID = 10 and s2.SubType2ID = 38 then 'Intermediate'
end as 'Sector'
from Products p
join Managers m on m.ManagerID = p.ManagerID
left join RFIFixedIncomeAttribution fia on fia.ParentID = p.ID and fia.ParentTypeID = 26
left join RFIFixedIncomeSectorAllocation sa on sa.RFIFixedIncomeAttributionID = fia.ID
and sa.RFIFixedIncomeDataTypeID = 1
join RFIFixedIncomeSectorCategories sc on sc.ID = sa.RFIFixedIncomeSectorCategoryID
join SubType1 s1 on s1.SubType1ID = p.SubType1ID
join SubType2 s2 on s2.SubType2ID = p.SubType2ID
join GeographicMandates gm on gm.GeographicMandateID = p.GeographicMandateID
where p.prodclasscategoryid = 4
and fia.year = 2014
and fia.quarter = 6/3
and p.Rank = 1
order by m.ManagerName, p.ProductName
--get filtered dataset
select * from #tmp
where
Sector in ('Core')
Second temp table:
--define temporary table
declare #tmp2 table (
ManagerID int null,
ManagerName varchar(250),
ProductID int null,
ProductName varchar(250),
RFIFixedIncomeAttributionID int null,
Value decimal(8,4) null,
Name varchar(250),
Sector varchar(250)
)
--populate temp table
insert into #tmp2
select
m.ManagerID, m.ManagerName, p.ID as 'ProductID', p.ProductName, sa.RFIFixedIncomeAttributionID, sa.Value, sc.Name,
case when gm.GeographicMandateID = 2 and s1.SubType1ID = 10 and s2.SubType2ID = 39 then 'Core'
when gm.GeographicMandateID = 2 and s1.SubType1ID = 10 and s2.SubType2ID = 38 then 'Intermediate'
end as 'Sector'
from Products p
join Managers m on m.ManagerID = p.ManagerID
join Vehicles v on v.ProductID = p.ID
join ManagerAccounts ma on ma.VehicleID = v.ID
join Accounts a on a.MgrAccountID = ma.MgrAccountID
left join RFIFixedIncomeAttribution fia on fia.ParentID = a.AccountID and fia.ParentTypeID = 6
left join RFIFixedIncomeSectorAllocation sa on sa.RFIFixedIncomeAttributionID = fia.ID
and sa.RFIFixedIncomeDataTypeID = 1
join RFIFixedIncomeSectorCategories sc on sc.ID = sa.RFIFixedIncomeSectorCategoryID
join SubType1 s1 on s1.SubType1ID = p.SubType1ID
join SubType2 s2 on s2.SubType2ID = p.SubType2ID
join GeographicMandates gm on gm.GeographicMandateID = p.GeographicMandateID
where p.prodclasscategoryid = 4
and fia.year = 2014
and fia.quarter = 6/3
and p.Rank = 1
order by m.ManagerName, p.ProductName
--get filtered dataset
select * from #tmp2
where
Sector in ('Core')
Few points that have already brought up
Union is the term you want, join is something quite different.
You are not working with temp tables, you are working with table variables. Not quite the same thing
mysql and mssql are not the same thing, tag your questions as one or the other, not both.
select * from #tmp
union all
select * from #tmp2 where productID not in (select productID from #tmp)
Not sure if I'd rely on this query in MySQL as it'll struggle with the not in clause...you can use the join syntax in Jasmine's answer for the second half of the union clause.
This is a case of "find all rows with NO MATCH in the other table" and we have a pattern for that. First, swap your tables - the table where you expect to be missing rows will be the second or RIGHT table, the other is the LEFT table.
select <columns>
from table1
LEFT OUTER JOIN table1.ID = table2.ID
where table2.ID IS NULL
OR... don't swap the tables and use RIGHT OUTER JOIN - but that's non-standard.
In your code, there's a problem...
and fia.quarter = 6/3
is equivalent to:
and fia.quarter = 2
I think you need some quotation marks there.

Case or If, What to choose in SQL

How can i manage this query. I want to have only one person in the query. If there is an id in empId column, then the name of him. Otherwise the name of the boss.
Product empId teamId
----------------------
A 1 3
B 2 4
C 3
D 2 3
E 4
User Table
Id Name
-----------
1 Jim
2 Carrey
3 Bill
4 Clinton
Team Table
Team_Id BossId
-----------
3 3
4 4
The result should look like:
Product user.name
-----------------
A Jim
B Carrey
C Bill
D Carrey
E Clinton
Use CASE or the COALESCE() function:
SELECT
x.Product
, COALESCE(emp.Name, boss.Name) AS Name
FROM
TableX AS x
LEFT JOIN
User AS emp
ON emp.Id = x.empId
LEFT JOIN
User AS boss
ON boss.Id = x.bossId
Updated:
SELECT
x.Product
, COALESCE(emp.Name, boss.Name) AS Name
FROM
TableX AS x
LEFT JOIN
User AS emp
ON emp.Id = x.empId
LEFT JOIN
Team As t
JOIN
User AS boss
ON boss.Id = t.bossId
ON t.team_Id = x.teamId
Something like this:
SELECT
Table1.Product,
CASE
WHEN Table1.empId IS NULL
THEN Boss.name
ELSE Emp.name
END
FROM
Table1
LEFT JOIN [User] AS Emp
ON Emp.Id =Table1.empId
LEFT JOIN Team
ON Team.Team_Id =Table1.teamId
LEFT JOIN [User] AS Boss
ON Boss.Id=Team.BossId
SELECT Y.Product, U.Name
FROM YourTable AS Y
JOIN Users AS U ON Y.empId = U.Id
UNION
SELECT Y.Product, U.Name
FROM YourTable AS Y
JOIN Team AS T ON Y.teamId = T.Team_Id
JOIN Users AS U ON T.BossId = U.Id
WHERE Y.empId IS NULL;
-- SET search_path='tmp';
DROP TABLE tmp.products;
CREATE TABLE products
( product CHAR(1)
, emp_id INTEGER
, team_id INTEGER
);
INSERT INTO products(product,emp_id,team_id)
VALUES ('A',1,3), ('B',2,4), ('C',NULL,3), ('D',2,3), ('E',NULL,4);
DROP TABLE tmp.names;
CREATE TABLE names
(id INTEGER
, zname varchar
);
INSERT INTO names(id,zname)
VALUES ( 1, 'Jim') ,( 2, 'Carrey') ,( 3, 'Bill') ,( 4, 'Clinton') ;
DROP TABLE tmp.teams;
CREATE TABLE teams
( team_id INTEGER NOT NULL
, boss_id INTEGER NOT NULL
);
INSERT INTO teams(team_id,boss_id) VALUES ( 3,4) , (4,4);
WITH lutser(prod,id,team) AS
(
SELECT k1.product AS prod
, k1.emp_id AS id
, k1.team_id AS team
FROM tmp.products k1
UNION
SELECT k2.product AS prod
, t.boss_id AS id
, k2.team_id AS team
FROM tmp.products k2
JOIN tmp.teams t ON t.team_id = k2.team_id
WHERE k2.emp_id IS NULL
)
SELECT l.prod
, l.id
, l.team
, n.zname
FROM lutser l
JOIN names n ON n.id = l.id
;
extra bonus point for a recursive version of this CTE ...