SQL - Поиск идентификатора внешнего ключа, связанного с комбинацией нескольких переменных строк таблицы переменных - PullRequest
1 голос
/ 10 марта 2020

В хранимой процедуре Microsoft SQL Server у меня есть табличная переменная @PlayerComboStrategy с переменным количеством строк и столбцами PLAYER_ID, POSITION_CODE, STATUS_CODE.

Я ищу наиболее эффективный способ получения STRATEGY_ID, связанного с точной комбинацией всех строк моей табличной переменной, если она существует. Другими словами, как я могу найти STRATEGY_ID, включающий все PLAYER_IDs с их спецификациями c POSITION_CODE и STATUS_CODE. Если его не существует, я продолжу его создание в своей хранимой процедуре.

Я думал о том, чтобы вытащить список всех STRATEGY_IDs для каждой строки, соответствующей комбинации PLAYER_ID, POSITION_CODE и STATUS_CODE, и посмотреть, существует ли общий идентификатор между списками. Однако это не удастся, если, например, три игрока (и их позиция и код статуса) связаны со стратегией, а точно такая же комбинация плюс один (или много) дополнительных игроков связаны с другой стратегией. При этом извлеченный STRATEGY_ID должен быть составлен из x чисел строк из PLAYER_STRATEGY, совпадающих с числом x строк из @PlayerComboStrategy.

Пример @PlayerComboStrategy

+-----------+---------------+-------------+
| PLAYER_ID | POSITION_CODE | STATUS_CODE |
+-----------+---------------+-------------+
|        33 |             2 |           2 |
|        23 |             4 |           1 |
+-----------+---------------+-------------+

Образец PLAYER_STRATEGY:

+-------------------+-------------+-----------+---------------+-------------+
| PLAYER_STATEGY_ID | STRATEGY_ID | PLAYER_ID | POSITION_CODE | STATUS_CODE |
+-------------------+-------------+-----------+---------------+-------------+
|              1490 |         511 |        64 |             2 |           2 |
|              1491 |         511 |        33 |             2 |           2 |
|              1492 |         511 |        23 |             4 |           1 |
|              1493 |         512 |        33 |             2 |           2 |
|              1494 |         512 |        23 |             5 |           1 |
|              1495 |         513 |        33 |             2 |           2 |
|              1496 |         513 |        23 |             4 |           1 |
|              1497 |         514 |        33 |             2 |           2 |
+-------------------+-------------+-----------+---------------+-------------+

Для этого примера я бы хотел найти STRATEGY_ID = 513 .

relationship diagram

Ответы [ 2 ]

1 голос
/ 11 марта 2020

Вот один из способов решения этой проблемы. Я включил полностью рабочий пример, чтобы вы могли увидеть хороший и простой способ обмена данными. :) Есть несколько способов, которыми вы можете заняться подобными вещами, но это то, что пришло мне в голову первым.

declare @PlayerStrategy table
(
    PLAYER_STATEGY_ID int
    , STRATEGY_ID int
    , PLAYER_ID int
    , POSITION_CODE int
    , STATUS_CODE int
)

insert @PlayerStrategy values
(1490, 511, 64, 2, 2)
, (1491, 511, 33, 2, 2)
, (1492, 511, 23, 4, 1)
, (1493, 512, 33, 2, 2)
, (1494, 512, 23, 5, 1)
, (1495, 513, 33, 2, 2)
, (1496, 513, 23, 4, 1)
, (1497, 514, 33, 2, 2)

declare @PlayerComboStrategy table
(
    PLAYER_ID int
    , POSITION_CODE int
    , STATUS_CODE int
)

insert @PlayerComboStrategy values
(33, 2, 2)
, (23, 4, 1)


select ps.STRATEGY_ID
from @PlayerStrategy ps
join @PlayerComboStrategy pcs on ps.PLAYER_ID = pcs.PLAYER_ID
                                        and ps.POSITION_CODE = pcs.POSITION_CODE
                                        and ps.STATUS_CODE = pcs.STATUS_CODE
group by ps.STRATEGY_ID
having count(ps.PLAYER_ID) = (select count(*) from @PlayerComboStrategy)
    and count(ps.PLAYER_ID) = (select count(*) from @PlayerStrategy ps2 where ps2.STRATEGY_ID = ps.STRATEGY_ID)
0 голосов
/ 10 марта 2020
WITH matching_strategies AS (
    SELECT strategy_id, COUNT(*) AS matching_strategies
    FROM @PlayerComboStrategy p
    JOIN PLAYER_STRATEGY s
        ON p.player_id = s.player_id
        AND p.position_code = s.position_code
        AND p.status_code = s.status_code
    GROUP BY strategy_id ),
total_strategies AS (
    SELECT p.strategy_id, COUNT(*) AS total_strategies
    FROM PLAYER_STRATEGY p
    JOIN matching_strategies s
        ON p.strategy_id = s.strategy_id
    GROUP BY p.strategy_id )
SELECT ms.strategy_id
FROM matching_strategies ms
JOIN total_strategies ts
    ON ms.strategy_id = ts.strategy_id
    AND ms.matching_strategies = ts.total_strategies
    AND matching_strategies = (SELECT COUNT(*) FROM @PlayerComboStrategy)

Первый CTE даст вам подсчет всех ваших стратегий, которые соответствуют игроку. Второй получит общее количество игроков в стратегии для тех, которые соответствуют одному из игроков, которых мы ищем. При окончательном выборе проверяется, совпадают ли подсчеты игроков с общим подсчетом и совпадает ли общее количество разыскиваемых игроков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...