SQL-запрос, чтобы соответствовать ВСЕ и соответствовать ЛЮБОМ - PullRequest
0 голосов
/ 14 декабря 2018

В настоящее время я использую MS SQL Server 2016. У меня есть две таблицы, которые используются для сбора запросов в течение дня для поиска деталей, которые соответствуют ВСЕМ или ЛЮБОМУ из запрошенных атрибутов детали:

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 атрибута части;ЛЮБОЙ из которых может присутствовать в части.

Следующий запрос сопоставляет запросы с частями, но не использует флаг (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 запросов и около 1,3 млн. частей в БД.

Любопытно, как другие решат эту проблемуконкретная проблема?Использование одного запроса или двух запросов (один для поиска ВСЕХ, другой для поиска ЛЮБЫХ)?

1 Ответ

0 голосов
/ 14 декабря 2018

Я думаю, что условное 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...