我有以下两个表field_allowed
和person
:
#person_id, field,
1 ,name
1 ,email
1 ,phone
2 ,name
2 ,phone
3 ,phone
#person_id, name, email, phone
1 , Mary, 123@example.com, 12345671
2 , John, 124@example.com, null
3 , Jack, 125@example.com, 12345673
我想要以下结果,对人员数据的访问控制:
#person_id, name, email, phone
1 , Mary, 123@example.com, 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)
将无法显示某些名称。
答案 0 :(得分:1)
利用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 123@example.com 12345671
2 John N/A null
3 N/A N/A 12345673