我有以下2个表field_allowedperson

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_CONCATLOCATE的使用似乎太脏了,必须有一种更好的方法。

因此,我想问一下是否有更好的方法可以做到上述几点?我可以控制数据库模式,因此可以更改模式,这也会有所帮助。

编辑:

请注意,如果找不到,则要求显示“ 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/

10-13 00:49