我当前正在使用MS SQL Server2016。我有两个表,它们用于全天收集请求以查找与所请求的零件属性的ALL或ANY匹配的零件:
CREATE TABLE requests (
r1_request_id int NOT NULL,
r1_match_type int NOT NULL,
CONSTRAINT PK_requests PRIMARY KEY CLUSTERED
(
r1_request_id ASC
)
);
CREATE TABLE request_attributes (
r2_request_id int NOT NULL,
r2_part_attribute int NOT NULL,
CONSTRAINT PK_request_attributes PRIMARY KEY CLUSTERED
(
r2_request_id ASC,
r2_part_attribute ASC
)
);
r1_match_type列包含1或2,其中:
1 =一部分中必须存在所有request_attributes
2 =一部分中可能存在任何request_attributes
第三张表是零件表:
CREATE TABLE parts (
p1_part_id int NOT NULL,
p1_attribute int NOT NULL,
CONSTRAINT PK_parts PRIMARY KEY CLUSTERED
(
p1_part_id ASC,
p1_attribute ASC
)
);
一天结束时,将执行查询以查找所有请求以及包含该请求的ANY或ALL属性的部分。例如,给定以下数据:
Table: parts
p1_part_id p1_attribute
10 1
10 2
10 3
10 4
20 1
20 2
20 3
20 4
30 2
30 4
Table: requests
r1_request_id r1_match_type
1 1
2 2
Table: request_attributes
r2_request_id r2_part_attribute
1 1
1 2
1 3
1 4
2 2
2 4
鉴于以上数据,请求1具有4个部分属性;所有这些属性必须存在于任何部分。请求2具有2个部分属性;其中的任何一个都可能存在。
以下查询将请求与零件匹配,但未使用用于指示请求零件属性是否必须与零件属性中的ALL或ANY匹配的标志(r1_match_type):
SELECT r1_request_id, p1_part_id, COUNT(*) AS attribute_count
FROM requests
JOIN request_attributes ON ( r2_request_id = r1_request_id )
JOIN parts ON ( p1_attribute = r2_part_attribute )
GROUP BY r1_request_id, p1_part_id
ORDER BY r1_request_id, p1_part_id
r1_request_id p1_part_id attribute_count
------------- ----------- ---------------
1 10 4
1 20 4
1 30 2
2 10 2
2 20 2
2 30 2
正确的输出需要考虑r1_match_type标志,并应产生如下所示的输出,因为请求1具有4个part属性,而一个部分中必须存在ALL 4属性(只有part 10和20具有所有4个属性)。
r1_request_id p1_part_id
------------- -----------
1 10
1 20
2 10
2 20
2 30
通常,一天中有将近50,000个请求,数据库中有130万个零件。
对其他人如何解决这个特定问题感到好奇吗?使用单个查询还是两个查询(一个查询查找全部,另一个查询查找ANY)?
答案 0 :(得分:1)
我认为条件HAVING
应该适合您。选中此选项,我认为它可以为您提供帮助:
SELECT r2_request_id
, p1_part_id
--,MAX(r1_match_type) match_type
,COUNT(*) AS attribute_count
FROM requests r
JOIN request_attributes ra1 ON ( r.r1_request_id = ra1.r2_request_id )
JOIN parts p ON ( p.p1_attribute = ra1.r2_part_attribute )
GROUP BY r2_request_id
, p.p1_part_id
HAVING ( MAX(r.r1_match_type)=2
OR COUNT(1)=(SELECT COUNT(1)
FROM request_attributes ra2
WHERE ra1.r2_request_id=ra2.r2_request_id)
)
ORDER BY ra1.r2_request_id
, p.p1_part_id