I am working on my highschool project I want to run a query for user to search medicines using multiple categories here is the ddl,
Create table medicine (
MedId int(11) NOT NULL AUTO_INCREMENT,
Name varchar(30) COLLATE utf8_bin DEFAULT NULL,
Vendor varchar(20) COLLATE utf8_bin DEFAULT NULL,
Quantity int(11) NOT NULL,
type text COLLATE utf8_bin NOT NULL,
price int(11) NOT NULL,
PRIMARY KEY (MedId)
);
create table category(
CatId smallint auto_increment,
Name varchar (20),
primary key(CatID)
);
create table MedicineCat(
MedId int,
CatId smallint,
foreign key (MedId) references medicine(MedId),
foreign key (CatId) references category(CatId),
primary key(MedId,CatId)
);
SELECT medicinecat.MedID AS 'MedId', medicine.Name AS 'Name', medicine.price AS 'Price', medicine.Quantity AS 'Quantity'
FROM medicinecat
JOIN medicine ON medicine.MedId = medicinecat.MedId
WHERE CatId in (1,2,3);
What I am getting is all the medicines that has at least one of the category , I know that's because of IN clause, what I want is to select medicine that has "all the categories" not one of the category.
select
m.MedID AS 'MedId',
m.Name AS 'Name',
m.price AS 'Price',
m.Quantity AS 'Quantity'
from medicine as m
where
exists (
-- to get only those having all three categories
select 1
from medicinecat as mc
where mc.CatId in (1,2,3) and mc.MedID = m.MedID
having count(*) = 3
)
If you can do some generic solution like
select
m.MedID AS 'MedId',
m.Name AS 'Name',
m.price AS 'Price',
m.Quantity AS 'Quantity'
from medicine as m
where
not exists (
select *
from (values (1), (2), (3)) as tt(CatId)
left outer join medicinecat as mc on mc.CatId = tt.CatId and mc.MedID = m.MedID
where mc.CatId is null
)
or
select
m.MedID AS 'MedId',
m.Name AS 'Name',
m.price AS 'Price',
m.Quantity AS 'Quantity'
from medicine as m
where
exists (
-- to get only those having all categories
select 1
from (values (1), (2), (3)) as tt(CatId)
left outer join medicinecat as mc on mc.CatId = tt.CatId and mc.MedID = m.MedID
having count(tt.CatId) = count(mc.CatId)
)