MySQL - 将行显示为列(尽可能简单)

Posted

技术标签:

【中文标题】MySQL - 将行显示为列(尽可能简单)【英文标题】:MySQL - Display rows as columns (as simple as possible) 【发布时间】: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 人,而下一个订单可能是一个人。

【问题讨论】:

【参考方案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 个订单

以上是关于MySQL - 将行显示为列(尽可能简单)的主要内容,如果未能解决你的问题,请参考以下文章

将行值转换为列,并计算所有可能值 mysql 的重复次数

如何将行显示为列?

分组后将行值显示为列-Oracle

将行数据拆分为列

如何在 MySQL 中将行数据转置为列

Mysql查询根据两列动态将行转换为列