Чтобы буквально ответить на ваш вопрос, вам просто нужно использовать MAX()
, так как PD
следует после Pr
.
SELECT
user_id,
account,
MAX(role) AS max_role
FROM
table
WHERE
account = '52501050'
GROUP BY
user_id,
account
Чтобы быть более обобщенным, есть много вариантов.
WITH
roles AS
(
SELECT 1 AS rank, 'PD/PI' AS role
UNION ALL
SELECT 2 AS rank, 'Principal Investigator' AS role
UNION ALL
SELECT 3 AS rank, 'another' AS role
),
grouped_data AS
(
SELECT
table.user_id,
table.account,
MIN(roles.rank) AS min_role_rank
FROM
table
INNER JOIN
roles
ON roles.role = table.role
GROUP BY
table.user_id,
table.account
)
SELECT
*
FROM
grouped_data
INNER JOIN
roles
ON roles.role = grouped_data.min_role_rank
Или ...
WITH
ranked_data AS
(
SELECT
table.*,
ROW_NUMBER() OVER (PARTITION BY table.user_id,
table.account
ORDER BY role_rank.id
)
AS user_role_rank
FROM
table
CROSS APPLY
(
SELECT
CASE table.role
WHEN 'PD/PI' THEN 1
WHEN 'Principal Investigator' THEN 2
WHEN 'an other' THEN 3
ELSE 4
END
AS id
)
role_rank
)
SELECT
*
FROM
ranked_data
WHERE
user_role_rank = 1
Или ...
WITH
roles AS
(
SELECT 1 AS rank, 'PD/PI' AS role
UNION ALL
SELECT 2 AS rank, 'Principal Investigator' AS role
UNION ALL
SELECT 3 AS rank, 'another' AS role
),
ranked_data AS
(
SELECT
table.*,
ROW_NUMBER() OVER (PARTITION BY table.user_id,
table.account
ORDER BY roles.rank
)
AS user_role_rank
FROM
table
INNER JOIN
roles
ON roles.role = table.role
)
SELECT
*
FROM
ranked_data
WHERE
user_role_rank = 1
В более совершенном мире у вас будет один user
или account
столЭто ограничено, так что это не может произойти.Затем вторая таблица user_role
для 0 .. многих ролей, с которыми может быть связан пользователь / учетная запись.
id | account user_id | role_id
----+--------- ---------+---------
11 | aaaaaaa 11 | 1
22 | bbbbbbb 11 | 2
22 | 2
22 | 3
Тогда у вас будет таблица role
с такими вещами, как ранжирующие порядковые числа....
role_id | rank | name | etc
---------+------+------+-----
1 | 30 | aa | ???
2 | 10 | bb | ???
3 | 20 | cc | ???
Тогда запрос становится относительно лаконичным ...
SELECT
*
FROM
user
CROSS APPLY
(
SELECT TOP 1 role.*
FROM user_role
JOIN role ON role.id = user_role.role_id
WHERE user_role.user_id = user.user_id
ORDER BY role.rank
)
AS role
(Это демонстрирует как другую структуру, так и другой подход, любой или оба могутбыть полезным для вас)
РЕДАКТИРОВАТЬ :
Я также заметил, что SQL SERVER
теперь поддерживает WITH TIES
для iveеще один подход.* (Аналогично подходу ROW_NUMBER()
, с немного более коротким кодом ...
SELECT TOP(1) WITH TIES
table.*
FROM
table
CROSS APPLY
(
SELECT
CASE table.role
WHEN 'PD/PI' THEN 1
WHEN 'Principal Investigator' THEN 2
WHEN 'an other' THEN 3
ELSE 4
END
AS id
)
role_rank
ORDER BY
ROW_NUMBER() OVER (PARTITION BY table.user_id,
table.account
ORDER BY role_rank.id
)
Сначала это может сбить с толку. Он выбирает первую строку (TOP(1)
) , нотакже все строки, которые связаны с ним, основаны на ORDER BY
. Таким образом, это функционально аналогично выполнению WHERE ROW_NUMBER() = 1
(но SQL Server не позволяет ROW_NUMBER()
быть в предложении WHERE
.)