【问题标题】:SQL Query Split columns into multiple rowsSQL 查询将列拆分为多行
【发布时间】:2017-10-25 14:44:32
【问题描述】:

这很可能以某种方式重复。我查看并尝试了许多找到的答案。我为此苦苦挣扎了好几天,但我无法让它发挥作用,或者弄清楚如何应用我找到的一些示例。

似乎最想将所有列转换为行,这不是我想要的。据我所知,我可能需要的是 unpivot 和/或 UNION?

我正在从 WordPress 表“wp_usermeta”中获取数据。

WordPress 表结构如下:

user_id | meta_key   | meta_value
1       | FirstnameA | Klaus
1       | SecondnameA| Reed
1       | FirstnameB | Herbert
1       | SecondnameB| Hall
2       | FirstnameA | Max
2       | SecondnameA| Musterman
....

我需要什么:

ID | Firstname_A | Lastname_A | Adress_A 

ID | Firstname_B | Lastname_B | Adress_B

两行将属于同一个 ID。

我当前的查询是什么样的:

SELECT user_id,

MAX(CASE WHEN meta_key='firstnameA' THEN meta_value ELSE null END)  FirstnameA,
MAX(CASE WHEN meta_key='lastnameA' THEN meta_value ELSE null END) Lastname_A,
MAX(CASE WHEN meta_key='adressA' THEN meta_value ELSE null END) Adress_A,
MAX(CASE WHEN meta_key='firstnameB' THEN meta_value ELSE null END) FirstnameB,
MAX(CASE WHEN meta_key='lastnameB' THEN meta_value ELSE null END) Lastname_B,
MAX(CASE WHEN meta_key='adressB' THEN meta_value ELSE null END) Adress_B

FROM wp_usermeta
GROUP BY user_id

我的结果是:

ID | Firstname_A | Lastname_A | Adress_A | Firstname_B | Lastname_B | Adress_B

MySQL-版本:5.7

我使用 JOIN for @janh 的方法也可以显示实际的 meta_key:

SET SQL_BIG_SELECTS=1;
select m1.user_id, m1.meta_value as Vorname_M, m2.meta_value as Nachname_M,m3.meta_value as Adresse_M,m4.meta_value as Telefon_M,m5.meta_value as Mail_M,
                   m6.meta_value as Vorname_V, m7.meta_value as Nachname_V,m8.meta_value as Adresse_V,m9.meta_value as Telefon_V,m10.meta_value as Mail_V,
                   m11.meta_value as Kinder, m12.meta_value as Kindergeburtstage,
                   m13.meta_value as Vorname_L, m14.meta_value as Nachname_L,m15.meta_value as Adresse_L,m16.meta_value as Telefon_L,m17.meta_value as Mail_L,
                   m18.meta_value as Arbeitskreise
from wp_usermeta m1
join wp_usermeta m2 on (m1.user_id = m2.user_id and m2.meta_key = 'nachnamemother')
join wp_usermeta m3 on (m2.user_id = m3.user_id and m3.meta_key = 'adress_mother')
join wp_usermeta m4 on (m3.user_id = m4.user_id and m4.meta_key = 'phone_mother')
join wp_usermeta m5 on (m4.user_id = m5.user_id and m5.meta_key = 'mail_mother')
join wp_usermeta m6 on (m5.user_id = m6.user_id and m6.meta_key = 'first_name_father')
join wp_usermeta m7 on (m6.user_id = m7.user_id and m7.meta_key = 'first_name_father_8')
join wp_usermeta m8 on (m7.user_id = m8.user_id and m8.meta_key = 'adress_father')
join wp_usermeta m9 on (m8.user_id = m9.user_id and m9.meta_key = 'phone_mother_16')
join wp_usermeta m10 on (m9.user_id = m10.user_id and m10.meta_key = 'mail_father')

join wp_usermeta m11 on (m10.user_id = m11.user_id and m11.meta_key = 'childs')
join wp_usermeta m12 on (m11.user_id = m12.user_id and m12.meta_key = 'birth_data')

join wp_usermeta m13 on (m12.user_id = m12.user_id and m13.meta_key = 'leben_vorname')
join wp_usermeta m14 on (m13.user_id = m13.user_id and m14.meta_key = 'leben_nachname')
join wp_usermeta m15 on (m14.user_id = m14.user_id and m15.meta_key = 'leben_adress')
join wp_usermeta m16 on (m15.user_id = m15.user_id and m16.meta_key = 'leben_phone')
join wp_usermeta m17 on (m16.user_id = m16.user_id and m17.meta_key = 'leben_mail')

join wp_usermeta m18 on (m17.user_id = m17.user_id and m18.meta_key = 'ak')

where m1.meta_key = 'firstnamemother'

什么对我有用:

SELECT user_id,

CASE WHEN meta_key LIKE '%mother' THEN 'mother' 
     WHEN meta_key LIKE '%father' THEN 'father' 
     WHEN meta_key LIKE '%8' THEN 'father'
     END AS AorB,


MAX(CASE WHEN meta_key='firstnamemother' 
           OR meta_key='first_name_father' 
         THEN meta_value END) AS Vorname,
        
MAX(CASE WHEN meta_key='nachnamemother' 
           OR meta_key='first_name_father_8' 
           THEN meta_value END) AS Nachname,
       
 MAX(CASE WHEN meta_key='adress_mother' 
           OR meta_key='adress_father' 
           THEN meta_value END) AS Adresse
       
FROM wp_usermeta
GROUP BY
user_id,
CASE WHEN meta_key LIKE '%mother' THEN 'mother' 
     WHEN meta_key LIKE '%father' THEN 'father' 
     WHEN meta_key LIKE '%8' THEN 'father'
     END

【问题讨论】:

    标签: sql wordpress split pivot-table


    【解决方案1】:

    UNION ALL 可以解决问题。

    SELECT user_id,
    MAX(CASE WHEN meta_key='firstnameA' THEN meta_value ELSE null END)  FirstnameA,
    MAX(CASE WHEN meta_key='lastnameA' THEN meta_value ELSE null END) Lastname_A,
    MAX(CASE WHEN meta_key='adressA' THEN meta_value ELSE null END) Adress_A
    FROM wp_usermeta
    GROUP BY user_id
    UNION ALL
    SELECT user_id,
    MAX(CASE WHEN meta_key='firstnameB' THEN meta_value ELSE null END) FirstnameB,
    MAX(CASE WHEN meta_key='lastnameB' THEN meta_value ELSE null END) Lastname_B,
    MAX(CASE WHEN meta_key='adressB' THEN meta_value ELSE null END) Adress_B
    FROM wp_usermeta
    GROUP BY user_id
    

    【讨论】:

    • 不能让它工作,它给了我一个“user_id”的语法错误。我确实删除了 Adress_A 之后的逗号,但仍然出现错误。
    • @Lpion 修正错字
    • @Matt 我首先尝试添加 SELECT,在我看到 Adress_A 之后的逗号太多之前,但后来我得到:'字段列表'中的未知列'user_id',即使在第一个 SELECT 似乎没有问题。我为 WP-Tablestructure 编辑了我的问题
    【解决方案2】:

    根据您对表格的编辑并希望 A 和 B 作为行而不是单独的列,您可以稍微更改条件聚合并添加一个新列来跟踪记录是 A 还是 B。然后按它和您的聚合进行分组应该给你想要的。

    SELECT
        ID
        ,CASE WHEN user_key LIKE '%A' THEN 'A' ELSE 'B' END AS AorB
        ,MAX(CASE WHEN meta_key LIKE 'first%' THEN meta_value END) AS FirstName
        ,MAX(CASE WHEN meta_key LIKE 'last%' OR meta_key LIKE 'sec%' THEN meta_value END) AS LastName
        ,MAX(CASE WHEN meta_key LIKE 'add%' THEN meta_value END) AS Address
    FROM
        wp_usermeta
    GROUP BY
        user_id
        ,CASE WHEN meta_key LIKE '%A' THEN 'A' ELSE 'B' END
    

    所以您只需要测试firstname 而不是firstnameb,因为如果您测试整个字符串,您将消除A 结果,lastname 和地址也是如此。请注意,在执行case expression 时,如果您不包含ELSE,则与when 语句不匹配的所有内容都将自动为NULL,因此您也可以将其排除。

    根据您的评论,您可以在 CASE 表达式中添加额外的 ORWHEN 语句,即使不标准应该只是 x# 的测试用例。加上使用first% 而不是firstname% 将立即占2 个案例,或者您可以考虑f%。最后你可以使用last%sec%等。

    如果您有特定数量的firstnameA,B,C,D。您也可以使用RIGHT(meta_key,1) 而不是case 表达式,只需在group by 中使用相同的东西。如果您有时需要超过 1 个字符而不是其他字符会变得更加困难,但您可以根据 case 表达式进行混合以进行测试,例如CASE WHEN meta_key LIKE '%AB' THEN RIGHT(meta_key,2) ELSE RIGHT(meta_key,1) END

    【讨论】:

    • 谢谢。这实际上看起来很棒。问题是,我没有对这个站点进行初始设置,并且 meta_keys(不是 user_key,抱歉)实际上并没有那么好组织。它更像 (firstname_A, secN),和那样的混乱。意思是 meta_keys 完全不同。但我会看看我是否还能以某种方式应用它。我还更正了我的问题中的列名。
    • @Lpion 检查我的编辑,我更新以说明您的表结构更改,但也更改了一些案例表达式以向您展示如何考虑“模糊”标准。以及处理 N (secN) 的一种可能不同的方式。
    • 谢谢。我在尝试。我编辑了我的问题并添加了我的 JOIN 方法,可以看到真正的 meta_keys。
    • @Lpion 是的,我是加入方法的赞成票,经过澄清后,这不是您想要做的正确方法。不幸的是,对于非标准数据,您在确定 meta_key 的值以及如何编写案例表达式时有点痛苦,但您可以从 wp_usermeta 执行 SELECT DISTINCT meta_key 以查看所有值并确定如何操作。
    • 非常感谢您抽出宝贵时间。你的解释很有帮助。我用现在对我有用的查询再次更新了我的问题。我希望一切都是正确的。
    【解决方案3】:

    我想连接应该这样做,不是吗?

    类似

    select ID, pm_firstname.meta_value as firstname, pm_lastname.meta_value lastname, pm_address.meta_value as address FROM wp_posts
        INNER JOIN wp_postmeta pm_firstname ON (wp_posts.ID = pm_firstname.post_id AND pm_firstname.meta_key = 'firstname')
        INNER JOIN wp_postmeta pm_lastname ON (wp_posts.ID = pm_lastname.post_id AND pm_lastname.meta_key = 'lastname')
        INNER JOIN wp_postmeta pm_address ON (wp_posts.ID = pm_address.post_id AND pm_address.meta_key = 'address')
    ;
    

    应该让你得到很好的组合结果。您需要哪种类型的联接取决于您的数据以及如果任何帖子都不存在字段会发生什么。

    【讨论】:

    • 我最初使用 JOIN,问题是它的性能很差。
    • 我想这取决于你到底做了什么,你是怎么做的,以及你认为表现不佳的地方。当您使用 WP_Query 来获取/查询查询中的元字段时,它也会使用连接,除非您缺少索引,否则它工作得很好。
    • 好吧,大约 5 行的性能还可以,但不止于此,它甚至不再显示结果,只是永远加载。
    • 这不应该发生。如果您将尝试与连接添加到问题中,我相信有人可以解释为什么他们没有执行。
    • 将我的 JOIN 方法添加到我的问题中。
    猜你喜欢
    • 2015-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-04
    • 1970-01-01
    • 1970-01-01
    • 2022-12-17
    相关资源
    最近更新 更多