【问题标题】:Is it possible to group rows this way using MySQL?是否可以使用 MySQL 以这种方式对行进行分组?
【发布时间】:2016-04-09 03:46:37
【问题描述】:

我有一个 MySQL 表,例如:

ID, USER, PARAM, VAL
--------------------
1 | 1 | NAME | ADAM
2 | 1 | AGE  | 15
3 | 2 | NAME | EVA
4 | 2 | AGE  | 16
5 | 3 | NAME | CRISS
6 | 3 | AGE  | 14

我很好奇是否有一个查询可以给我类似的信息:

1 | ADAM | 15
2 | EVE  | 16
3 | CRISS| 14

到目前为止,我只是使用以下查询并将记录分组到一个循环中。

SELECT * FROM table WHERE PARAM ='NAME' OR PARAM = 'AGE'

我尝试使用GROUP,但没有成功。

【问题讨论】:

  • 你为什么要这样组织表格?
  • 这太可恶了。说真的。
  • @SBI 相当常见 - 请参阅 EAV
  • @BoristheSpider 哦,我很清楚这一点。不过不会改变我对它的看法。不会因为人们在使用它而变得更好。这是对关系数据库在优化、简洁查询等方面为您提供的功能的完全滥用。这正是许多数据库试图避免/规避它的原因(mssql 中的稀疏列,带有 xpath 子查询的 postgres)。
  • 不可能!您的数据有“Eva”,而您想要“Eve”。我们不是奇迹工作者 :-)

标签: php mysql sql


【解决方案1】:

在同一张表上使用join:

SELECT a.USER user_id, a.VAL user_name, b.VAL user_age
FROM `table` a
INNER JOIN `table` b ON a.USER = b.USER
WHERE a.PARAM = 'NAME'
AND b.PARAM = 'AGE'

结果:

user_id     user_name   user_age
1           ADAM        15
2           EVA         16
3           CRISS       14

【讨论】:

  • 与 max/group by 相比,这是一种更好的方法。
  • @SalmanA 为什么? AFAIK 情况更糟。尝试使用超过 1 或 2 个值来获取,您需要为每个新列连接。
【解决方案2】:

无需使用 JOIN。试试这个:

SELECT USER,
       MAX(CASE PARAM WHEN 'NAME' THEN VAL ELSE NULL END) AS NAME,
       MAX(CASE PARAM WHEN 'AGE' THEN VAL ELSE 0 END) AS AGE
FROM test 
GROUP BY USER;

【讨论】:

  • 这很有效,我有时会使用它,例如在 ETL 的数据转换中。您可以删除ELSE NULL 使其更短且更具可读性(并考虑可读性,添加一些换行符)
  • 我已经使用了这两种查询方式来解决这个问题,我可以说这个查询速度更快,而且在我看来更具可读性,尤其是当您需要检查大量用户属性时。
  • ELSE NULL 没用,但在某些情况下ELSE 0 可能明显是错误的。现在投票给@Abhik Chakraborty
【解决方案3】:

您可以使用最常用的技术来生成透视视图

select
user,
max(case when param = 'NAME' then val end) as name,
max(case when param = 'AGE' then val end) as age
from mytable
group by user

【讨论】:

    【解决方案4】:

    你可以这样查询:

    SELECT t1.user,
            (
               SELECT val FROM tab1 t2 
               WHERE t2.user = t1.user 
                 AND t2.param = 'Name'
            ) name,
            (
               SELECT val FROM tab1 t2 
               WHERE t2.user = t1.user 
                 AND t2.param = 'Age'
            ) age
        FROM tab1 t1
        GROUP BY user
    

    另一种可能性是 group_concat,但是你让所有值都在一个列中侦听。

    SELECT user, group_concat(param, ':', val)
        FROM tab1
        GROUP BY user
    

    【讨论】:

      【解决方案5】:

      您好,我在我的数据库示例中复制了您的问题,请尝试以下查询:

          SELECT t1.USER,VAL,(SELECT VAL AS AGE FROM table1 where USER = t1.USER AND PARAM = 'AGE') as AGE 
          FROM table1 t1
          WHERE param = 'NAME'
      

      或者在你的桌子上使用 join:

      SELECT a.USER, a.VAL, b.VAL
      FROM table1  t1
      INNER JOIN table1 t2 
      ON t1.USER = t2.USER
      WHERE t1.PARAM = 'NAME'
      AND t2.PARAM = 'AGE'
      

      将 table1 替换为您的表名。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-01-04
        • 1970-01-01
        • 2022-01-20
        • 2011-12-28
        • 1970-01-01
        • 1970-01-01
        • 2017-03-04
        相关资源
        最近更新 更多