SQL 查询匹配所有和匹配任何
SQL query to match ALL and match ANY
我目前正在使用 MS SQL Server 2016。我有两个 table 用于全天收集请求以查找与所有或任何请求部分匹配的部分属性:
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 = ALL request_attributes 必须出现在部分中
2 = 任何 request_attributes 可能出现在部分中
第三个table是部分table:
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
)
);
在一天结束时执行查询以查找所有请求和包含该请求的任何或所有属性的部分。例如,给定以下数据:
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 个部分属性;其中任何一个都可能出现在某个部分中。
以下查询将请求与部件匹配,但不使用标志 (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 个部分属性并且所有 4 个属性必须存在于一个部分中(仅第 10 和 20 部分)具有所有 4 个属性)。
r1_request_id p1_part_id
------------- -----------
1 10
1 20
2 10
2 20
2 30
通常情况下,全天有近 50,000 个请求,数据库中有大约 130 万个部分。
想知道其他人会如何解决这个特殊问题吗?使用单个查询或两个查询(一个查找全部,另一个查找任意)?
我认为条件 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
我目前正在使用 MS SQL Server 2016。我有两个 table 用于全天收集请求以查找与所有或任何请求部分匹配的部分属性:
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 = ALL request_attributes 必须出现在部分中
2 = 任何 request_attributes 可能出现在部分中
第三个table是部分table:
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
)
);
在一天结束时执行查询以查找所有请求和包含该请求的任何或所有属性的部分。例如,给定以下数据:
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 个部分属性;其中任何一个都可能出现在某个部分中。
以下查询将请求与部件匹配,但不使用标志 (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 个部分属性并且所有 4 个属性必须存在于一个部分中(仅第 10 和 20 部分)具有所有 4 个属性)。
r1_request_id p1_part_id
------------- -----------
1 10
1 20
2 10
2 20
2 30
通常情况下,全天有近 50,000 个请求,数据库中有大约 130 万个部分。
想知道其他人会如何解决这个特殊问题吗?使用单个查询或两个查询(一个查找全部,另一个查找任意)?
我认为条件 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