【问题标题】:MySQL - Display rows as columns (as simple as possible)MySQL - 将行显示为列(尽可能简单)
【发布时间】:2016-02-28 16:40:19
【问题描述】:

几周以来,我一直在处理以下问题。我已经阅读了我找到的所有教程和 sn-ps,但无法完成这项工作。

我有下表(wordpress 数据库):

post_id  meta_key              meta_value
802      _billing_first_name   John
802      _billing_last_name    Johnson
802      _billing_first_name2  Jack
802      _billing_last_name2   Jackson
802      _billing_first_name3  Jason
802      _billing_last_name3   Jasonson
803      _billing_first_name   Jamie
803      _billing_last_name    Jameson
803      _billing_first_name2  Oliver
803      _billing_last_name2   Olverson

我需要一份所有订单中所有人的名单。该列表应如下所示。

ID    Firstname    Lastname
802   John         Johnson
802   Jack         Jackson
802   Jason        Jasonson
803   Jamie        Jameson
803   Oliver       Oliverson

每个订单可能有无限的名称。一个订单可能是 20 人,而下一个订单可能是一个人。

【问题讨论】:

    标签: php mysql sql json wordpress


    【解决方案1】:

    您可以使用自加入:

    SELECT t1.post_id AS ID, t1.meta_value AS Firstname, t2.meta_value AS Lastname
    FROM tab t1
    JOIN tab t2
      ON t1.post_id = t2.post_id
     AND t1.meta_key LIKE '_billing_first_name%'
     AND t2.meta_key LIKE '_billing_last_name%'
     AND RIGHT(t1.meta_key, 3) = RIGHT(t2.meta_key,3);  -- up to 999 users
    

    LiveDemo

    输出:

    ╔═════╦═══════════╦══════════╗
    ║ ID  ║ FirstName ║ LastName ║
    ╠═════╬═══════════╬══════════╣
    ║ 802 ║ John      ║ Johnson  ║
    ║ 802 ║ Jack      ║ Jackson  ║
    ║ 802 ║ Jason     ║ Jasonson ║
    ║ 803 ║ Jamie     ║ Jameson  ║
    ║ 803 ║ Oliver    ║ Olverson ║
    ╚═════╩═══════════╩══════════╝
    

    重点是MySQL关系型数据库,不适用于EAV 设计。这个解决方案在非常大的表中可能会很慢,因为连接条件是non-SARGable

    编辑:

    我猜你想加入:

    _billing_first_name2_billing_email002

    您可以使用普通数字处理000,但性能会很差:

    SELECT t1.post_id AS ID, t1.meta_value AS Firstname, t2.meta_value AS Email
    FROM tab t1
    JOIN tab t2
      ON t1.post_id = t2.post_id
     AND t1.meta_key LIKE '_billing_first_name%'
     AND t2.meta_key LIKE '_billing_last_email%'     --email
     AND CONCAT(
          IF(SUBSTRING(t1.meta_key,-3,1) REGEXP '[0-9]',SUBSTRING(t1.meta_key,-3,1), '0'),
          IF(SUBSTRING(t1.meta_key,-2,1) REGEXP '[0-9]',SUBSTRING(t1.meta_key,-2,1), '0'),
          IF(SUBSTRING(t1.meta_key,-1,1) REGEXP '[0-9]',SUBSTRING(t1.meta_key,-1,1), '0')
            ) = 
          CONCAT(
          IF(SUBSTRING(t2.meta_key,-3,1) REGEXP '[0-9]',SUBSTRING(t2.meta_key,-3,1), '0'),
          IF(SUBSTRING(t2.meta_key,-2,1) REGEXP '[0-9]',SUBSTRING(t2.meta_key,-2,1), '0'),
          IF(SUBSTRING(t2.meta_key,-1,1) REGEXP '[0-9]',SUBSTRING(t2.meta_key,-1,1), '0')
            )
    

    【讨论】:

    • 我喜欢你的解决方案,你能解释一下你是如何正确链接名字和姓氏的吗?即杰克和杰克逊而不是奥尔弗森。由于您不能使用 ID 作为参考(并且希望表格正确排序。我仍在尝试在我自己的查询中弄清楚这一点
    • @davejal 每个带有 EAV 设计的键都有编号,最后AND RIGHT(t1.meta_key, 3) = RIGHT(t2.meta_key,3); 完成这项工作。只是 "ne2" = "ne2", "ne3" = "ne3" ...
    • 感谢您的跟进。不过,我将不得不查找 eav 设计
    • 谢谢 lad2025。漂亮而简单的代码。当我们获得超过 999 个用户时会发生什么。 IE。 5 个用户的 200 个订单。
    • @Virik 它将工作到_billing_first_name999。如果需要更多信息,您需要使用AND RIGHT(t1.meta_key, 4) = RIGHT(t2.meta_key,4);。总记录数不受此限制,因此您可以拥有 100 个用户,每个用户有 999 个订单
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    • 1970-01-01
    • 1970-01-01
    • 2019-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多