通过中间M:N(MySQL)

时间:2018-03-22 09:43:23

标签: mysql sql

我遇到了一个我试图解决的问题,希望得到一些帮助......

这是数据库的布局:

database

目标如下:

problem objective

请注意:

name1 - supplier (e.g., S1, S2, etc.)
name3 - component (e.g., C1, C2, etc.)
name5 - assembly (e.g., A1, A2, etc.)
output - cost for various combinations of supplier-component

我开发的以下(不完整)查询找到了与组件级别(III)相关的最小输出,但它没有执行在多组件装配级别(II)添加最小值的中间步骤查询。

select t5.name5, min(output) as min_output
from t5
inner join t4
    on t5.id5 = t4.id5
inner join t2
    on t4.id3 = t2.id3
group by t5.name5
order by t5.id5
;

产生的错误输出仅显示以下内容:

name5          min_output
-----|---------------------------
A    | minimum of component A
B    | minimum of component B

期望的结果是A& A的II级和。 B级III级组件(关于输出最小化),针对每个列出的I级/名称5(即使用相应组件/供应商最小化组装成本)。

如果有的话,我怎么能用上面的查询来解决这个问题呢?我觉得我错过了一些嵌套条件。

此外,我如何确定来自t1(供应商)的任何条目是否未被使用?我会以某种方式使用外部联接吗?

谢谢你的时间!

编辑2

Per Gordon的建议,这里是完整的数据集供参考:

CREATE DATABASE IF NOT EXISTS DB;

USE DB;

CREATE TABLE t3 (
    id3 INT AUTO_INCREMENT NOT NULL,
    name3 VARCHAR(255),
    PRIMARY KEY (id3)
);

CREATE TABLE t1 (
    id1 INT AUTO_INCREMENT NOT NULL,
    name1 VARCHAR(255),
    PRIMARY KEY (id1)
);

CREATE TABLE t5 (
    id5 INT AUTO_INCREMENT NOT NULL,
    name5 VARCHAR(255),
    PRIMARY KEY (id5)
);

CREATE TABLE t4 (
    id5 INT,
    id3 INT,
    FOREIGN KEY (id5)
        REFERENCES t5 (id5),
    FOREIGN KEY (id3)
        REFERENCES t3 (id3)
);

CREATE TABLE t2 (
    id2 INT AUTO_INCREMENT NOT NULL,
    id1 INT,
    id3 INT,
    output INT,
    PRIMARY KEY (id2),
    FOREIGN KEY (id1)
        REFERENCES t1 (id1),
    FOREIGN KEY (id3)
        REFERENCES t3 (id3)
);

insert into t3(name3)
    values('C1');
insert into t3(name3)
    values('CS2');
insert into t3(name3)
    values('C3');
insert into t3(name3)
    values('C4');
insert into t3(name3)
    values('C5');
insert into t3(name3)
    values('C6');

insert into t1(name1)
    values('S1');
insert into t1(name1)
    values('S2');
insert into t1(name1)
    values('S3');
insert into t1(name1)
    values('S4');
insert into t1(name1)
    values('S5');

insert into t5(name5)
    values('A1');
insert into t5(name5)
    values('A2'); 
insert into t5(name5)
    values('A3');  
insert into t5(name5)
    values('A4');

insert into t4(id5, id3)
    values(1,1);
insert into t4(id5, id3)
    values(2,2);
insert into t4(id5, id3)
    values(2,3);
insert into t4(id5, id3)
    values(3,4);
insert into t4(id5, id3)
    values(3,5);
insert into t4(id5, id3)
    values(4,6);
insert into t4(id5, id3)
    values(4,3);

insert into t2(id1, id3, output)
    values(1,1,121);
insert into t2(id1, id3, output)
    values(1,2,135);
insert into t2(id1, id3, output)
    values(2,2,94);    
insert into t2(id1, id3, output)
    values(2,3,155);
insert into t2(id1, id3, output)
    values(3,3,178);
insert into t2(id1, id3, output)
    values(3,4,199);
insert into t2(id1, id3, output)
    values(4,4,122);
insert into t2(id1, id3, output)
    values(4,5,155);
insert into t2(id1, id3, output)
    values(5,5,133);
insert into t2(id1, id3, output)
    values(5,6,184);

我原始查询的输出如下:

name5          min_output
-----|---------------------------
A1   |       121
A2   |       94
A3   |       122
A4   |       155

预期输出为:

name5          min_output
-----|---------------------------
A1   |       121
A2   |       249
A3   |       255
A4   |       339

此外,我如何确定来自t1(供应商)的任何条目是否未被使用?我会基于(正确的)结果表以某种方式使用带有NULL的外连接吗?

预期产出:

unused_name1
--------------|
       S3     |

P.S。好的电话,谢谢戈登!

1 个答案:

答案 0 :(得分:0)

我认为以下查询将解决您的问题;它基本上是你的查询,但是在t2上将min(输出)移动到子查询中,从而允许在顶层完成一个总和:

select t5.name5, sum(t2m.cost) as min_output
from t5 
left join t4 on t4.id5 = t5.id5 
left join (select id3, min(output) as cost from t2 group by id3) as t2m on t2m.id3 = t4.id3 
group by t5.name5 
order by t5.id5 

输出:

 name5  min_output  
 A1     121
 A2     249
 A3     255
 A4     339

对于未使用的供应商/组件对(即组件成本高于最小值的供应商),此查询将检索它们:

select distinct t1.name1, t2.id3
from t5
left join t4
    on t4.id5 = t5.id5
left join t2
    on t2.id3 = t4.id3
left join t1
    on t1.id1 = t2.id1
where t2.output != (select min(output) from t2 where id3 = t4.id3)
order by t1.id1

输出:

 name1  id3     
 S1     2
 S3     3
 S3     4
 S4     5

此查询将提供没有任何最低成本组件的供应商列表,以及它们提供的组件数量(为了获得名称,您可以从中选择名称作为子查询)。

select t1.name1, t1c.cmpcount
from t5
left join t4
    on t4.id5 = t5.id5
left join t2
    on t2.id3 = t4.id3
left join t1
    on t1.id1 = t2.id1
left join (select id1, count(id3) as cmpcount from t2 group by id1) as t1c
    on t1c.id1 = t2.id1
where t2.output != (select min(output) from t2 where id3 = t4.id3)
group by t1.name1
having count(distinct t2.id3) = t1c.cmpcount

输出

name1   cmpcount    
S3      2