我想返回一个任意选择的值,以查询具有多行的数据源。
user_id account role
paa2013 52501050 PD/PI
paa2013 52501050 Principal Investigator
user_id account role
paa2013 52501050 PD/PI
select distinct
user_id,
account,
case
when role = 'PD/PI' then 'PD/PI'
when role = 'Principal Investigator' then 'Principal Investigator'
end
from table
where account = '52501050'
group by
user_id,
account,
case
when role = 'PD/PI' then 'PD/PI'
when role = 'Principal Investigator' then 'Principal Investigator'
end
user_id account role
paa2013 52501050 PD/PI
paa2013 52501050 Principal Investigator
感谢您的帮助!
答案 0 :(得分:1)
要从字面上回答您的问题,您只需要使用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..many角色。
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
(这说明了不同的结构和方法,或者对您有所帮助)
EDIT :
我还注意到SQL SERVER
现在支持WITH TIES
以提供另一种方法。 *(类似于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
子句中。)
答案 1 :(得分:0)
您可以在row_number()
子句中使用ORDER BY
,在其中为角色分配优先级。
SELECT user_id,
account,
role
FROM (SELECT user_id,
account,
role,
row_number() OVER (PARTITION BY user_id,
account
ORDER BY CASE role
WHEN 'PD/PI' THEN
1
WHEN 'Principal Investigator' THEN
2
...
END) rn
FROM table) x
WHERE rn = 1;
答案 2 :(得分:-1)
如果要保留给定列选择的第一行,只需使用“限制”功能。 Limit函数旁边的参数用于表示应满足给定查询的应返回的行数。
select user_id, account, role from raw_data limit 1;
但是,如果要为给定的userid-account-role组合保留第一个条目,则将数据设置为给定条件的子集并使用限制。例如,下面的补丁程序会将选择查询限制为特定帐户(= 52501050),并返回第一行。
select user_id, account, role from raw_data where account = '52501050' limit 1;