SQL查询以匹配ALL和ANY

时间:2018-12-14 16:02:35

标签: sql sql-server-2008 query-performance

我当前正在使用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)?

1 个答案:

答案 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