How to do distinct join on more than 3 tables - mysql

CREATE TABLE Application
(
ID_Application INT,
ID_Owner1 INT,
ID_Owner2 INT,
ID_Owner3 INT,
Name varchar(200) NOT NULL
);
CREATE TABLE `Person`
(
ID_Person INT,
Name varchar(200) NOT NULL
);
CREATE TABLE `PersonInOrg`
(
ID_Person INT,
ID_Org INT
);
CREATE TABLE `Org`
(
ID_Org INT,
ID_Owner1 INT,
ID_Owner2 INT,
ID_Owner3 INT,
Name varchar(200) NOT NULL
);
INSERT INTO Application
(ID_Application, ID_Owner1, ID_Owner2, ID_Owner3, Name)
VALUES ( 123,11,21,null,"A"),
( 124,11,null,32,"B"),
( 125,11, null,null,"C");
INSERT INTO Person
(ID_Person, Name)
VALUES ( 12345,"Peter"),
( 12346,"Rafi"),
( 12347,"Rafael");
INSERT INTO PersonInOrg
(ID_Person, ID_Org)
VALUES ( 12345,1234),
( 12346,1111),
( 12347,1212);
INSERT INTO Org
(ID_Org, ID_Owner1, ID_Owner2, ID_Owner3, Name)
VALUES ( 1234,11,21,null,"Org1"),
( 1111,12,null,32,"Org2"),
( 1212,13, null,null,"Org3");
Fiddle Link
I want to see the list of owners for all applications. The below picture explains the relations between the lists of tables.
------>Application
ID_Application; ID_Owner1; ID_Owner2; ID_Owner3;Name
------>Person
ID_Person; Name
------->PersonInOrg
ID_Person; ID_Org
------->Org
ID_Org; ID_Owner1; ID_Owner2; ID_Owner3; Name
Expected result -->List of applications with names for each owner as below:
ID_Application;ID_Owner1; ID_Owner2; ID_Owner3; ID_Person_1; ID_Person_2; ID_Person_3
SELECT a.id_application,
a.id_owner1,
a.id_owner2,
a.id_owner3,
p.id_person AS [ID_Person1],
p.id_person AS [ID_Person2],
p.id_person AS [ID_Person3]
FROM application AS a
JOIN org AS o
ON a.id_owner1 = o.id_owner1
OR a.id_owner2 = o.id_owner2
OR a.id_owner3 = o.id_owner3
JOIN pesoninorg AS po
ON o.id_org = po.id_org
JOIN person AS p
ON po.id_org = p.id_person
Sample data

Consider:
Query1: AppUNION
SELECT ID_Application, ID_Owner1 AS Owner, 1 AS Seq FROM Application
UNION SELECT ID_Application, ID_Owner2, 2 FROM Application
UNION SELECT ID_Application, ID_Owner3, 3 FROM Application;
Query2: OrgPIO_UNION
SELECT Org.ID_Org, ID_Owner1 AS OwnerID, ID_Person, "ID_Person1" AS Seq FROM Org
INNER JOIN PersonInOrg ON Org.ID_Org = PersonInOrg.ID_Org
UNION SELECT Org.ID_Org, ID_Owner2, ID_Person, "ID_Person2" FROM Org
INNER JOIN PersonInOrg ON Org.ID_Org = PersonInOrg.ID_Org
UNION SELECT Org.ID_Org, ID_Owner3, ID_Person, "ID_Person3" FROM Org
INNER JOIN PersonInOrg ON Org.ID_Org = PersonInOrg.ID_Org;
Query3: AppPersonCROSS
TRANSFORM First(OrgPIO_UNION.ID_Person) AS FirstOfID_Person
SELECT AppUNION.ID_Application
FROM AppUNION INNER JOIN OrgPIO_UNION ON AppUNION.Owner = OrgPIO_UNION.OwnerID
GROUP BY AppUNION.ID_Application
PIVOT OrgPIO_UNION.Seq;
Query4:
SELECT Application.*, ID_Person1, ID_Person2, ID_Person3
FROM AppPersonCROSS
INNER JOIN Application ON AppPersonCROSS.ID_Application = Application.ID_Application;

Related

How to intersect between a view and a table in mysql?

I've a view and a table. I'm inserting data into table on the basis of that view. I want that view to eliminate same data that is already inserted into table.
This is the view which is named view_1.
CREATE VIEW view_1 AS
SELECT
y.employee_registration_id,
x.employee_first_name,
x.employee_last_name,
x.employee_email,
y.employee_current_salary_amount,
(SELECT
x.salary_of_year_month_YearMonth
FROM
salary_of_years_months x
LEFT JOIN
status_salary_of_years_months y ON x.salary_of_year_month_id = y.salary_of_year_month_id
WHERE
y.year_month_status = 'Ongoing') AS salary_of_year_month_YearMonth,
(SELECT
CONCAT(MONTHNAME(x.salary_of_year_month_YearMonth),
'-',
YEAR(x.salary_of_year_month_YearMonth))
FROM
salary_of_years_months x
LEFT JOIN
status_salary_of_years_months y ON x.salary_of_year_month_id = y.salary_of_year_month_id
WHERE
y.year_month_status = 'Ongoing') AS salary_of_year_month_YearMonth_MonthYear
FROM
basic_info_employees x
LEFT JOIN
current_salary_employees y ON x.employee_registration_id = y.employee_registration_id
WHERE
y.employee_current_salary_amount > 0;
This is the table.
CREATE TABLE `salary_tracker_employees` (
serial_no INT(4) NOT NULL AUTO_INCREMENT,
employee_registration_id INT(4),
employee_first_name VARCHAR(30),
employee_last_name VARCHAR(30),
employee_email VARCHAR(30),
salary_of_year_month_YearMonth VARCHAR(50),
employee_current_salary_amount DOUBLE(8 , 2 ),
PRIMARY KEY (serial_no),
UNIQUE (employee_registration_id , salary_of_year_month_YearMonth)
);
I want to get a view that will intersect the between view_1 and salary_tracker_employees.

Combine the results of two queries into one

I am trying to make the following query in MySQL:
Find the IDs of the suppliers that supply all the parts in red or green.
The structure of the tables would be this:
proveedores(ID: int (PK), nombre: nvarchar, direccion: nvarchar)
partes(ID: int (PK), nombre: nvarchar, color: nvarchar)
catalogo(proveedores_ID: int (FK), partes_ID: int (FK), costo: double)
And I have managed to make a querys that allows me to see the IDs of the suppliers that distribute all the parts of red or green as the case may be.
The query using "red" or "Green" is this:
SELECT DISTINCT C.proveedores_ID FROM fabrica.catalogo C
WHERE NOT EXISTS (
SELECT P.ID FROM fabrica.partes P
WHERE P.color = "red" AND ( NOT EXISTS (
SELECT C1.proveedores_ID FROM fabrica.catalogo C1
WHERE C1.proveedores_ID = C.proveedores_ID AND C1.partes_ID = P.ID
)
)
);
but I could not combine it to generate a query that allows me to return the previously given requirement.
I would appreciate if someone can help me achieve the expected result.
You can join two NOT EXISTS conditions with an OR to fetch providers for whom there aren't red parts they haven't sold, or there aren't green parts they haven't sold:
SELECT DISTINCT C.proveedores_ID FROM fabrica.catalogo C
WHERE NOT EXISTS (
SELECT P.ID FROM fabrica.partes P
WHERE (P.color = "red")
AND ( NOT EXISTS (
SELECT C1.proveedores_ID FROM fabrica.catalogo C1
WHERE C1.proveedores_ID = C.proveedores_ID
AND C1.partes_ID = P.ID
)
)
) OR NOT EXISTS (
SELECT P.ID FROM fabrica.partes P
WHERE (P.color = "green")
AND ( NOT EXISTS (
SELECT C1.proveedores_ID FROM fabrica.catalogo C1
WHERE C1.proveedores_ID = C.proveedores_ID
AND C1.partes_ID = P.ID
)
)
);

MySQL find results based on two different values of the same column

list employees names (Ename) who have both 49008 zip code customers and 49009 zip code customers.
I am struggling to answer the above query based on the above tables.
If the names match between tables assume constraint.
I can filter down to name and zip easily by left joins and group by but struggle after that, I don't know the proper where or having statement. I am assuming it could be done better by a sub query but not sure. Ideally, a single query.
Please and thank you.
1) Create and insert statements for example data:
Create table Employees (EM_Eno INT NOT NULL, EM_Ename VARCHAR(50), EM_Hire_Date DATE, PRIMARY KEY(EM_Eno));
Create table Customers (Customers_Cno INT NOT NULL, Customers_Cname VARCHAR(50), Customers_Street VARCHAR(50), Customers_Zip INT, Customers_Phone INT, primary key(Customers_Cno));
Create table Orders (Orders_Ono INT NOT NULL, Orders_Cno INT, Orders_Eno INT, Orders_Received DATE, Orders_Shipped DATE, primary key(Orders_Ono));
insert into Orders values
( 1,301,501,20161010,20161011);
( 2,302,501,20161011,20161012);
( 3,303,502,20161110,20161111);
( 4,304,502,20161110,20161112);
( 5,305,502,20161110,20161113);
( 6,306,503,20161112,20161114);
( 7,307,501,20161112,20161113);
( 8,308,503,20161112,20161115);
( 9,309,503,20161115,20161120);
(10,300,501,20161112,20161113);
insert into Customers values
(300,'Bryan','100 street',49009,1234567890),
(301,'Ryan','101 street',49008,1234567890),
(302,'Nick','102 street',49009,1234567890),
(303,'Nicholas','103 street',49009,1234567890),
(304,'Alexa','104 street',49009,1234567890),
(305,'Tori','105 street',49008,1234567890),
(306,'Scarlet','106 street',49008,1234567890),
(307,'Heather','100 street',49009,1234567890),
(308,'Amanda','107 street',49008,1234567890),
(309,'James','108 street',49008,1234567890);
insert into Employees values
(501,'Robert',20041010),
(502,'Sam',20050110),
(503,'Brandy',20050710);
2) Ideal end result is answering the query "list employees (names) who have both 49008-zipcode customers and 49009-zipcode customers."
3) Best Attempt thus far:
select Employees.EM_Ename
, Customers.Customers_Zip
from Employees
left
join Orders
on Employees.EM_Eno = Orders.Orders_Eno
left
join Customers
on Orders.Orders_Cno = Customers.Customers_Cno
group
by Employees.EM_Ename
, Customers.Customers_Zip;
The table names are altered slightly in the rextest, because other tables already exist there with the same name...
SELECT e.*
FROM tbl_employees e
JOIN tbl_orders o
ON o.orders_eno = e.em_eno
JOIN tbl_customers c
ON c.Customers_Cno = o.Orders_Cno
WHERE c.Customers_Zip IN(49008,49009)
GROUP
BY e.em_eno
HAVING COUNT(DISTINCT customers_zip) = 2;
http://rextester.com/HCNLU51847
This should be what you want:
select Min(e.Ename)
from #Employees e
join #Orders o on o.Eno = e.Eno
join #Customers c on c.Cno = o.Cno
join #Orders o2 on o2.Eno = e.Eno
join #Customers c2 on c2.Cno = o2.Cno
where o.Ono !=o2.Ono--c.Cno != c2.Cno and
and c.Zip = 49008 and c2.Zip = 49009
group by e.Ename,c.Zip
order by e.Ename
As you can see if you wanted more than those two the self joins become longer.

MySQL: Multiple Joins to Same Table & then to Another Table in Same Row

I am working in LAMP environment.
In MySQL I have 3 tables & I want to create the desired report as mentioned in below attached image.
How I can achieve this.
Because of table ProductMaster allowing non-ID integers in its FK_ProductTag_# fields, a special join is needed for each Attribute (assuming each FK_ProductTag_# can have a "0" value. Here is the requested query:
select a.ProductName as 'Product Name',
a.Attr1 as 'Atrribute-1',
b.Attr2 as 'Attribute-2',
c.Attr3 as 'Atrribute-3' from
(select m.ProductName as 'ProductName',
concat_ws(': ', tagtype.Description, tag1.Description) as 'Attr1'
from ProductMaster m
left join ProductTag tag1 on m.FK_ProductTag_1 = tag1.ID
left join ProductTagType tagtype on tag1.FK_ProductTagType = tagtype.ID) as a
join
(select m.ProductName as 'ProductName',
concat_ws(': ', tagtype.Description, tag2.Description) as 'Attr2'
from ProductMaster m
left join ProductTag tag2 on m.FK_ProductTag_2 = tag2.ID
left join ProductTagType tagtype on tag2.FK_ProductTagType = tagtype.ID) as b
on a.ProductName = b.ProductName
join
(select m.ProductName as 'ProductName',
concat_ws(': ', tagtype.Description, tag3.Description) as 'Attr3'
from ProductMaster m
left join ProductTag tag3 on m.FK_ProductTag_3 = tag3.ID
left join ProductTagType tagtype on tag3.FK_ProductTagType = tagtype.ID) as c
on a.ProductName = c.ProductName
order by a.ProductName asc
See this SQLFiddle for a demo.
SQLFiddle was acting up during testing, so copy the above query and the below table schema into SQLTest for a demo:
create table ProductTagType (ID int not null auto_increment, Description varchar(20), primary key (ID));
create table ProductTag (ID int not null auto_increment, Description varchar(20), FK_ProductTagType int(1), primary key (ID));
create table ProductMaster (ID int not null auto_increment, ProductName varchar(20), FK_ProductTag_1 int(1), FK_ProductTag_2 int(1), FK_ProductTag_3 int(1), primary key (ID));
insert into ProductTagType (Description)
values ('Imported'), ('Local'), ('HomeMade');
insert into ProductTag (Description, FK_ProductTagType)
values ('Wood', 2), ('Plastic', 2), ('Steel', 1), ('Aluminum', 3);
insert into ProductMaster (ProductName, FK_ProductTag_1, FK_ProductTag_2, FK_ProductTag_3)
values ('Chair', 1, 2, 3), ('Table', 0, 3, 4);

SQL transfer data to another table using join

I have old tables
Items(vendorId-FK, ManufacturerId (IS NOT FK)),
Vendors(PK- VendorId int),
Manufacturer(PK-ManufacturerId int)
Need to transfer data to new DB and it works on transferring data from vendor, but from Manufacturer it transfer only 30000 (where oldManufacturerId is not null), and other 5000 is not transferred. Any ideas what I'm doing wrong?
New Table Manufacturer
( OldManufacturerID int,
newManufacturerId Uniqueidentifier default newid(),
ManufacturerName varchar (100),
)
New Table Items
( ...
ItemDescription,
ManufacturerId uniqueidentifier,
VendorId uniqueidentifier
)
INSERT INTO dbo.Item
( ...
ItemDescription,
ManufacturerId ,
VendorId
)
SELECT
...
itemDescription,
m.ManufacturerId ,
v.VendorId
FROM OldSqlDatabase.dbo.tbl_Items i
JOIN NewSqlDatabase.dbo.Vendor v ON ISNULL(i.vendor_id, '') = ISNULL(v.SourceVendorID, '')
JOIN NewSqlDatabase.dbo.Manufacturer m ON ISNULL(i.manufacturer_id, '') = ISNULL(m.SourceManufacturerID, '')
I just transfered a data since this table didn't have any relationships, new manufactureId has default newid(), and this new id i want to use in the new item table
INSERT INTO dbo.Manufacturer
( OldManufacturerID ,
ManufacturerName ,
)
SELECT
manufacturer_id ,
manufacturer_name ,
FROM oldManufacture
You likely need to use a LEFT JOIN the get records where there a no values (null values) on which to join. The LEFT JOIN will allow you to select all records from the first table being specified in the join, even if there are no matching records available in the second table in the join.
This would also allow you to get rid of that ISNULL() stuff in the join definitions as well. Those would perform very poorly, as they would not be able to use indexes.
I would suggest something like:
INSERT INTO dbo.Item
( ...
ItemDescription,
ManufacturerId ,
VendorId
)
SELECT
...
itemDescription,
m.ManufacturerId ,
v.VendorId
FROM OldSqlDatabase.dbo.tbl_Items i
LEFT JOIN NewSqlDatabase.dbo.Vendor v
ON i.vendor_id = v.SourceVendorID
LEFT JOIN NewSqlDatabase.dbo.Manufacturer m
ON i.manufacturer_id = m.SourceManufacturerID