我有以下2个表field_allowed
和person
:
field_allowed
#person_id, field,
1 ,name
1 ,email
1 ,phone
2 ,name
2 ,phone
3 ,phone
人
#person_id, name, email, phone
1 , Mary, [email protected], 12345671
2 , John, [email protected], null
3 , Jack, [email protected], 12345673
我想要以下结果,对人员数据的访问控制:
#person_id, name, email, phone
1 , Mary, [email protected], 12345671
2 , John, N/A , null
3 , N/A , N/A , 12345673
我只找到一种愚蠢的方法来实现此输出
SELECT
person.person_id,
CASE
WHEN LOCATE('name', GROUP_CONCAT(DISTINCT field)) THEN person.name
ELSE 'N/A'
END AS name,
CASE
WHEN LOCATE('email', GROUP_CONCAT(DISTINCT field)) THEN person.email
ELSE 'N/A'
END AS email,
CASE
WHEN LOCATE('phone', GROUP_CONCAT(DISTINCT field)) THEN person.phone
ELSE 'N/A'
END AS phone
FROM
person
JOIN
field_allowed ON field_allowed.person_id = person.person_id
GROUP BY person.person_id
我发现
GROUP_CONCAT
和LOCATE
的使用似乎太脏了,必须有一种更好的方法。因此,我想问一下是否有更好的方法可以做到上述几点?我可以控制数据库模式,因此可以更改模式,这也会有所帮助。
编辑:
请注意,如果找不到,则要求显示“ N / A”,并且名称可以少于3个字符。因此,答案
MAX(CASE WHEN f.field = 'name' THEN name ELSE '' END) AS name)
将无法显示某些名称。 最佳答案
利用MAX
中的NULL
和非空字符串将返回非空字符串的事实,您可以仅使用条件聚合来获得所需的结果。如果没有可用值,则MAX
将返回NULL
,并且COALESCE
可用于将该值转换为N/A
:
SELECT p.person_id,
COALESCE(MAX(CASE WHEN f.field = 'name' THEN name END), 'N/A') AS name,
COALESCE(MAX(CASE WHEN f.field = 'email' THEN email END), 'N/A') AS email,
COALESCE(MAX(CASE WHEN f.field = 'phone' THEN phone END), 'N/A') AS phone
FROM person p
JOIN field_allowed f ON f.person_id = p.person_id
GROUP BY p.person_id
输出:
person_id name email phone
1 Mary [email protected] 12345671
2 John N/A null
3 N/A N/A 12345673
Demo on dbfiddle
关于mysql - 性能问题:一种更好的方法:“先案例,先定位,然后再分组”,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54662522/