排除一对多查询的结果
Excluding results from One to Many query
我很难从一对多 table 关系中提取数据。 我需要列出尚未应用 "Echo" 保修代码的设备合同列表。
在我的场景中,我有一份设备合同 table 和一份保修单 table。
设备合同table(以下简称EQC)的设计是:
------------------------------------------------------------------------------------
| EquipmentID | Contract | SerialNumber | Make | Model | Date | Customer |
------------------------------------------------------------------------------------
| 001 | A1 | GDS12 | GRND | GR219 | 2016-03-02 | Acme Corp|
| 002 | B1 | BQWSD | BQW | BLU22 | 2016-03-10 | Fast Lawn|
| 003 | C1 | Foo36 | Foo | Red18 | 2016-03-04 | Perfect T|
| 004 | D1 | Foo37 | Foo | Red18 | 2016-03-04 | Perfect T|
| 005 | E1 | Foo38 | Foo | Red18 | 2016-03-01 | Perfect T|
------------------------------------------------------------------------------------
质保书table(以下简称WAR)的设计为:
---------------------------------------------------
| SerialNum | Make | WarrantyCode | Warranty Date|
---------------------------------------------------
| GDS12 | GRND | Alpha | 2016-04-01 |
| GDS12 | GRND | Bravo | 2016-04-01 |
| GDS12 | GRND | Delta | 2016-04-01 |
| GDS12 | GRND | Charlie | 2016-04-01 |
| GDS12 | GRND | Echo | 2016-04-01 |
| BQWSD | BQW | Alpha | 2016-04-01 |
| BQWSD | BQW | Bravo | 2016-04-01 |
| BQWSD | BQW | Charlie | 2016-04-01 |
| BQWSD | BQW | Foxtrot | 2016-04-01 |
| BQWSD | BQW | Echo | 2016-04-01 |
| Foo36 | Foo | Alpha | 2016-04-01 |
| Foo36 | Foo | Bravo | 2016-04-01 |
| Foo36 | Foo | Charlie | 2016-04-01 |
| Foo36 | Foo | Hotel | 2016-04-01 |
---------------------------------------------------
我需要做的是列出尚未应用 "Echo" 保修代码的 EQC。也就是说要么没有Echo记录,要么还没有保修记录期。
我的结果集应该如下所示:
------------------------------------------------------------------------------------
| EquipmentID | Contract | SerialNumber | Make | Model | Date | Customer |
------------------------------------------------------------------------------------
| 003 | C1 | Foo36 | Foo | Red18 | 2016-03-04 | Perfect T|
| 004 | D1 | Foo37 | Foo | Red18 | 2016-03-04 | Perfect T|
| 005 | E1 | Foo38 | Foo | Red18 | 2016-03-01 | Perfect T|
------------------------------------------------------------------------------------
(GDS12 和 BQWSD 被排除在外,因为它们应用了 Echo 保修代码。)
我的查询是:
SELECT EQC.EquipmentID
,EQC.Contract
,EQC.SerialNumber
,EQC.Make
,EQC.Model
,EQC.DATE
,EQC.Customer
FROM equipment - contracts EQC
LEFT JOIN warranty WAR
ON WAR.SerialNum = EQC.SerialNumber
AND WAR.Make = EQC.Make
WHERE WAR.WarrantyCode is null
OR WAR.WarrantyCode <> 'Echo'
结果集如下所示:
------------------------------------------------------------------------------------
| EquipmentID | Contract | SerialNumber | Make | Model | Date | Customer |
------------------------------------------------------------------------------------
| 001 | A1 | GDS12 | GRND | GR219 | 2016-03-02 | Acme Corp|
| 001 | A1 | GDS12 | GRND | GR219 | 2016-03-02 | Acme Corp|
| 001 | A1 | GDS12 | GRND | GR219 | 2016-03-02 | Acme Corp|
| 001 | A1 | GDS12 | GRND | GR219 | 2016-03-02 | Acme Corp|
| 002 | B1 | BQWSD | BQW | BLU22 | 2016-03-10 | Fast Lawn|
| 002 | B1 | BQWSD | BQW | BLU22 | 2016-03-10 | Fast Lawn|
| 002 | B1 | BQWSD | BQW | BLU22 | 2016-03-10 | Fast Lawn|
| 002 | B1 | BQWSD | BQW | BLU22 | 2016-03-10 | Fast Lawn|
| 003 | C1 | Foo36 | Foo | Red18 | 2016-03-04 | Perfect T|
| 003 | C1 | Foo36 | Foo | Red18 | 2016-03-04 | Perfect T|
| 003 | C1 | Foo36 | Foo | Red18 | 2016-03-04 | Perfect T|
| 003 | C1 | Foo36 | Foo | Red18 | 2016-03-04 | Perfect T|
| 004 | D1 | Foo37 | Foo | Red18 | 2016-03-04 | Perfect T|
| 005 | E1 | Foo38 | Foo | Red18 | 2016-03-01 | Perfect T|
------------------------------------------------------------------------------------
您想要 不存在的 EQC 一个 Echo WAR。或者换句话说:您想要 不在 Echo WAR 集合中的 EQC。
select *
from equipment eqc
where not exists
(
select *
from warranty war
where war.serialnum = eqc.serialnumber
and war.make = eqc.make
and war.warrantycode = 'Echo'
);
或者:
select *
from equipment
where (serialnumber, make) not in
(
select serialnum, make
from warranty
where warrantycode = 'Echo'
);
更新: 但是,我不确定 SQL 服务器是否支持 IN 子句中的元组,如上所示。正如您所见,这是一个很棒的功能,它使查询真正可读,但不幸的是,某些 DBMS 不支持此语法。
我很难从一对多 table 关系中提取数据。 我需要列出尚未应用 "Echo" 保修代码的设备合同列表。 在我的场景中,我有一份设备合同 table 和一份保修单 table。
设备合同table(以下简称EQC)的设计是:
------------------------------------------------------------------------------------
| EquipmentID | Contract | SerialNumber | Make | Model | Date | Customer |
------------------------------------------------------------------------------------
| 001 | A1 | GDS12 | GRND | GR219 | 2016-03-02 | Acme Corp|
| 002 | B1 | BQWSD | BQW | BLU22 | 2016-03-10 | Fast Lawn|
| 003 | C1 | Foo36 | Foo | Red18 | 2016-03-04 | Perfect T|
| 004 | D1 | Foo37 | Foo | Red18 | 2016-03-04 | Perfect T|
| 005 | E1 | Foo38 | Foo | Red18 | 2016-03-01 | Perfect T|
------------------------------------------------------------------------------------
质保书table(以下简称WAR)的设计为:
---------------------------------------------------
| SerialNum | Make | WarrantyCode | Warranty Date|
---------------------------------------------------
| GDS12 | GRND | Alpha | 2016-04-01 |
| GDS12 | GRND | Bravo | 2016-04-01 |
| GDS12 | GRND | Delta | 2016-04-01 |
| GDS12 | GRND | Charlie | 2016-04-01 |
| GDS12 | GRND | Echo | 2016-04-01 |
| BQWSD | BQW | Alpha | 2016-04-01 |
| BQWSD | BQW | Bravo | 2016-04-01 |
| BQWSD | BQW | Charlie | 2016-04-01 |
| BQWSD | BQW | Foxtrot | 2016-04-01 |
| BQWSD | BQW | Echo | 2016-04-01 |
| Foo36 | Foo | Alpha | 2016-04-01 |
| Foo36 | Foo | Bravo | 2016-04-01 |
| Foo36 | Foo | Charlie | 2016-04-01 |
| Foo36 | Foo | Hotel | 2016-04-01 |
---------------------------------------------------
我需要做的是列出尚未应用 "Echo" 保修代码的 EQC。也就是说要么没有Echo记录,要么还没有保修记录期。
我的结果集应该如下所示:
------------------------------------------------------------------------------------
| EquipmentID | Contract | SerialNumber | Make | Model | Date | Customer |
------------------------------------------------------------------------------------
| 003 | C1 | Foo36 | Foo | Red18 | 2016-03-04 | Perfect T|
| 004 | D1 | Foo37 | Foo | Red18 | 2016-03-04 | Perfect T|
| 005 | E1 | Foo38 | Foo | Red18 | 2016-03-01 | Perfect T|
------------------------------------------------------------------------------------
(GDS12 和 BQWSD 被排除在外,因为它们应用了 Echo 保修代码。)
我的查询是:
SELECT EQC.EquipmentID
,EQC.Contract
,EQC.SerialNumber
,EQC.Make
,EQC.Model
,EQC.DATE
,EQC.Customer
FROM equipment - contracts EQC
LEFT JOIN warranty WAR
ON WAR.SerialNum = EQC.SerialNumber
AND WAR.Make = EQC.Make
WHERE WAR.WarrantyCode is null
OR WAR.WarrantyCode <> 'Echo'
结果集如下所示:
------------------------------------------------------------------------------------
| EquipmentID | Contract | SerialNumber | Make | Model | Date | Customer |
------------------------------------------------------------------------------------
| 001 | A1 | GDS12 | GRND | GR219 | 2016-03-02 | Acme Corp|
| 001 | A1 | GDS12 | GRND | GR219 | 2016-03-02 | Acme Corp|
| 001 | A1 | GDS12 | GRND | GR219 | 2016-03-02 | Acme Corp|
| 001 | A1 | GDS12 | GRND | GR219 | 2016-03-02 | Acme Corp|
| 002 | B1 | BQWSD | BQW | BLU22 | 2016-03-10 | Fast Lawn|
| 002 | B1 | BQWSD | BQW | BLU22 | 2016-03-10 | Fast Lawn|
| 002 | B1 | BQWSD | BQW | BLU22 | 2016-03-10 | Fast Lawn|
| 002 | B1 | BQWSD | BQW | BLU22 | 2016-03-10 | Fast Lawn|
| 003 | C1 | Foo36 | Foo | Red18 | 2016-03-04 | Perfect T|
| 003 | C1 | Foo36 | Foo | Red18 | 2016-03-04 | Perfect T|
| 003 | C1 | Foo36 | Foo | Red18 | 2016-03-04 | Perfect T|
| 003 | C1 | Foo36 | Foo | Red18 | 2016-03-04 | Perfect T|
| 004 | D1 | Foo37 | Foo | Red18 | 2016-03-04 | Perfect T|
| 005 | E1 | Foo38 | Foo | Red18 | 2016-03-01 | Perfect T|
------------------------------------------------------------------------------------
您想要 不存在的 EQC 一个 Echo WAR。或者换句话说:您想要 不在 Echo WAR 集合中的 EQC。
select *
from equipment eqc
where not exists
(
select *
from warranty war
where war.serialnum = eqc.serialnumber
and war.make = eqc.make
and war.warrantycode = 'Echo'
);
或者:
select *
from equipment
where (serialnumber, make) not in
(
select serialnum, make
from warranty
where warrantycode = 'Echo'
);
更新: 但是,我不确定 SQL 服务器是否支持 IN 子句中的元组,如上所示。正如您所见,这是一个很棒的功能,它使查询真正可读,但不幸的是,某些 DBMS 不支持此语法。