Combine the results of two queries into one - mysql

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
)
)
);

Related

How to do distinct join on more than 3 tables

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;

left join query keep a column empty

I have a two table called PaymentMaster and PaymentDetails and two table joined by receiptID column. This is my query
SELECT pm.receiptID
, pm.recievedAmount
, pd.invono
, pd.paidAmount
FROM PaymentMaster pm
LEFT JOIN PaymentDetail pd ON pd.receiptID = pm.receiptID
following query provide me this result
note that there are two records in PaymentDetails regarding receiptID PAY0002. That is why two records show for PAY0002. (INV0001,INV0002).
the issue is, I do not want to print PAY0002 in two rows. if the id is same then the column should be empty.The end result should be like this
You can use GROUP BY keyword for grouping them, your query will become something like this
SELECT pm.receiptID
, pm.recievedAmount
, pd.invono
, pd.paidAmount
FROM PaymentMaster pm LEFT JOIN PaymentDetail pd ON pd.receiptID = pm.receiptID GROUP BY pd.receiptID
You could use a variable to control what you display
drop table if exists pm,pd;
create table pm(id varchar(8), amt int);
create table pd(id varchar(8), amt int);
insert into pm values ('aaa',1000),('bbb','100');
insert into pd values ('aaa',100),('aaa',100),('bbb',100);
Select case when rn = 1 then pmid else '' end as pmid,
case when rn = 1 then pmamt else '' end as pmamt,
pdid,pdamt
from
(
select pm.id pmid,pm.amt pmamt,
pd.id pdid, pd.amt pdamt
,if(pm.id<> #p, #rn:=1,#rn:=#rn+1) rn
,#p:=pm.id
from pm
join pd on pd.id = pm.id
,(select #rn:=0,#p:=0) rn
) s

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.

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

SQL Comparing 2 values that must be determined

I need to Find out the course with the most passes from my table tblResults.
tblResults:
StuID Course Symbol
1001 CSC101 P
1001 RNG101 F
1002 CSC101 P
1002 RNF101 F
1003 HAP101 P
1004 HAP101 P
i.e should give CSC101 (And all other courses (HAP101) with the same ammount of passes)
I have tried:
CREATE VIEW Part1 AS
SELECT NumbF
FROM
(SELECT COUNT(Course) AS NumbP,
Course
FROM tblResults
WHERE Symbol = 'P')
GROUP BY Course);
CREATE VIEW Part2 AS
SELECT MAX(NumbP) AS Maxnum
FROM Part1,
tblResults
WHERE Symbol = 'P'
GROUP BY Course;
SELECT Part1.Course
FROM Part1,
Part2
WHERE Part1.NumbP = Part2.MaxNum
But I seem to be doing something incorrectly. Please help
Something like this should work:
create view yourview as
select course, count(*) passcnt
from tblResults
where symbol = 'P'
group by course
select *
from yourview
where passcnt = (select max(passcnt) from yourview)
SQL Fiddle Demo
Note, you don't need the view, I just left it for simplicity.
SELECT Course, count(StuID) count
FROM tblResults
GROUP BY Course
HAVING count = (SELECT max(c)
FROM (SELECT count(StuID) c, Course
FROM tblResults
GROUP BY Course
WHERE Symbol = 'p'
) counts
);
You can try the SELECT below, but I haven't tested it:
SELECT selA.Course, selA.NumPass FROM (
SELECT Course, COUNT(Course) AS NumPass FROM
tblResults GROUP BY Course HAVING Symbol = 'P') AS selA
INNER JOIN (
SELECT MAX(NumPassCount) AS NumPassMax FROM (
SELECT COUNT(Course) AS NumPassCount FROM
tblResults GROUP BY Course HAVING Symbol = 'P') AS selB)
AS selC ON selA.NumPass = selC.NumPassMax
Using a couple of sub queries
SELECT Sub3.Course
FROM
(
SELECT MAX(Course) AS MaxCourseCnt
FROM
(
SELECT Course, COUNT(*) AS CourseCnt
FROM tblResults
WHERE Symbol = 'P'
GROUP BY Course
) Sub1
) Sub2
INNER JOIN
(
SELECT Course, COUNT(*) AS CourseCnt
FROM tblResults
WHERE Symbol = 'P'
GROUP BY Course
) Sub3
ON Sub2.MaxCourseCnt = Sub3.CourseCnt