MySQL查询将规范化数据转换为单行

时间:2014-07-10 22:22:49

标签: mysql sql

我正在尝试创建一个查询,将规范化表格中的内容格式化为单行。

我想要的是这样的,每个联系人都有一行:

Name               Mobile            Office          Home
---------------    -----------       ----------      ----------
Fred Flintstone    123-456-7890      234-567-8901    789-012-3456  
Barney Rubble      456-789-0123                      678-901-2345
Wilma Flintstone   567-890-1234                      789-012-3456

我从最新查询得到的是这样,每个联系人有多行:

Name               Phone           Phone_Type
---------------    ------------    -----------
Fred Flintstone    123-456-7890    Mobile
Fred Flintstone    234-567-8901    Office
Fred Flintstone    789-012-3456    Home
Barney Rubble      456-789-0123    Mobile
Barney Rubble      678-901-2345    Home
Wilma Flintstone   567-890-1234    Mobile
Wilma Flintstone   789-012-3456    Home

以下是涉及的表格(简化):

contacts
----------
contact_id
name

link_contact_phonenumbers
-------------------------
contact_id
phone_number_id

phone_numbers
-------------
phone_number_id
phone_number
type_id

ref_phone_types
---------------
type_id
name

这是我到目前为止所做的:

SELECT 
    cn.name as Name,
    concat( left(ph.phone_number,3) , "-" , mid(ph.phone_number,4,3) , "-", right(ph.phone_number,4)) as Phone,
    pt.name as Phone_Type
FROM
    contacts cn
    LEFT JOIN link_contact_phonenumbers lp ON lp.contact_id = cn.contact_id
    LEFT JOIN phone_numbers ph ON ph.phone_number_id = lp.phone_number_id
    LEFT JOIN ref_phone_types pt ON pt.type_id = ph.type_id

我查看了使用GROUP_CONCAT()函数,但是它将所有内容都拉到了一个列中。我需要他们进入他们自己的专栏。

我一直在研究与IF()结合的子查询,但还没有想出来。

有没有办法在纯SQL中执行此操作?

2 个答案:

答案 0 :(得分:0)

听起来你可以用几个连接来完成你想要的东西:

Select a.name, c.phone_number, d.phone_number, e.phone_number from contacts a 
    left join link_contact_phonenumbers b on a.contact_id = b.contact_id 
    left join phone_numbers c on b.phone_number_id = c.phone_number_id and c.type_id = "whatever id is mobile"
    left join phone_numbers d on b.phone_number_id = d.phone_number_id and d.type_id = "whatever id is office"
    left join phone_numbers e on b.phone_number_id = e.phone_number_id and e.type_id = "whatever id is home"

我不知道这是否是最有效的方法,我现在也没有数据库可以测试它可能会关闭,但它应该指向正确的方向。如果第一个连接添加多行,也可能需要按a.name分组。

答案 1 :(得分:0)

以下是将来会发现这一点的其他解决方案:

SELECT 
    cn.name as Name,
    MAX(CASE WHEN pt.type_id = '1' THEN ph.phone_number ELSE NULL END) as Mobile,
    MAX(CASE WHEN pt.type_id = '2' THEN ph.phone_number ELSE NULL END) as Office,
    MAX(CASE WHEN pt.type_id = '3' THEN ph.phone_number ELSE NULL END) as Home      
FROM
    contacts cn
    LEFT JOIN link_contact_phonenumbers lp ON lp.contact_id = cn.contact_id
    LEFT JOIN phone_numbers ph ON ph.phone_number_id = lp.phone_number_id
    LEFT JOIN ref_phone_types pt ON pt.type_id = ph.type_id
GROUP BY cn.contact_id

在此处找到此解决方案:How to Denormalize a Normalized Table Using SQL

我不确定这是否效率最高,但确实有效。