【问题标题】:find rows that have multiple linked rows查找具有多个链接行的行
【发布时间】:2015-05-17 11:20:05
【问题描述】:

我正在做我的高中项目 我想为用户运行查询以使用多个类别搜索药物 这是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);

我得到的是至少有一个类别的所有药物,我知道这是因为 IN 子句, 我想要的是选择具有“所有类别”而不是类别之一的药物。

【问题讨论】:

  • MySQL 和/或 SQL Server? (不要标记未涉及的产品...)
  • 感谢先生的提示,但 sql server 或 mysql 并不重要,我问的是任何一个产品都相同的 dml

标签: mysql sql sql-server sqlite relational-division


【解决方案1】:
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
    )

如果你能做一些通用的解决方案,比如

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
    )

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

【讨论】:

    【解决方案2】:

    几个选项(未经测试)

    类别计数 声明 @categoryCount int SET @categoryCount = (SELECT COUNT(*) FROM Category WHERE catid IN (1,2,3))

    SELECT medicine.MedID AS 'MedId', medicine.Name AS 'Name', medicine.price AS 'Price', medicine.Quantity AS 'Quantity'
    FROM Medicine
    WHERE @categoryCount = (SELECT COUNT(*) FROM MedicineCat WHERE MedicineCat.MedId = Medicine.MedId)
    

    分组方式 + 拥有

    SELECT medicine.MedID AS 'MedId', medicine.Name AS 'Name', medicine.price AS 'Price', medicine.Quantity AS 'Quantity'
    FROM Medicine
        JOIN MedicineCat ON Medicine.MedId = MedicineCat.MedId
    GROUP BY medicine.MedID, medicine.Name, medicine.price, medicine.Quantity
    HAVING COUNT(*) = @categoryCount
    

    多个存在

    SELECT medicine.MedID AS 'MedId', medicine.Name AS 'Name', medicine.price AS 'Price', medicine.Quantity AS 'Quantity'
    FROM Medicine
    WHERE EXISTS (SELECT 1 FROM MedicineCat WHERE MedicineCat.MedId = 1)
        AND EXISTS (SELECT 1 FROM MedicineCat WHERE MedicineCat.MedId = 2)
        AND EXISTS (SELECT 1 FROM MedicineCat WHERE MedicineCat.MedId = 3)
    

    【讨论】:

    • 好吧,如果类别中存在 1,2,3 以外的其他类别并且 MedicineCat 具有 1,2,4 或 2,4,5 等组合,则前两个解决方案将返回不正确的结果
    猜你喜欢
    • 1970-01-01
    • 2016-01-19
    • 2013-05-13
    • 1970-01-01
    • 2020-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多