如何将行显示为具有其他值的动态列?

时间:2016-04-04 14:11:10

标签: mysql

我想显示具有collect_id = 2的订单商品 我希望将与每个order_item相关的所有字段显示为具有值的列。

这些是表格和结果:

+-------------------------------+
|         order_item            |
+-------------------------------+
| oi_id  oi_price oi_collect_id |
| 1         100         2       |
| 2         30          2       |
| 3         55          3       |
| 4         70          4       |
| 5         220         2       |
| 6         300         4       |
+-------------------------------+

+-----------------------------------+
|            field_value            |
+-----------------------------------+
| v_value    v_fk_field_id oi_fk_id |
|  Peter             1        1     |
|  Lagaf             2        1     |
|  Football          3        1     |
|  Male              4        1     |
|  12345678          5        1     |
|  Frank             1        2     |
|  Loran             2        2     |
|  Tennis            3        2     |
|  Male              4        2     |
|  11223658          5        2     |
|  Nathali           1        5     |
|  Waton             2        5     |
|  Reading           3        5     |
+-----------------------------------+

oi_fk_id : foreign key ref(order_item.oi_id)
v_fk_field_id : foreign key ref(field.f_id)

+--------------------+
|       field        |
+--------------------+
| f_id      f_label  |
| 1          surname |
| 2          name    |
| 3          hobbies |
| 4          sex     |
| 5          phone   |
+--------------------+

+-----------------------------------------------------------------------------+
|                                   Result                                    |
+-----------------------------------------------------------------------------+
|  oi_id  oi_price oi_collect_id surname    name    hobbies    sex    phone   |
|  1         100         2        Peter     Lagaf   Football   Male  12345678 |
|  2         30          2        Frank     Loran    Tennis    Male  11223658 |
|  5         220         2       Nathali    Waton   Reading    null    null   |
+-----------------------------------------------------------------------------+

重要提示:表格字段不仅包含这5个字段(名称,姓氏,爱好,性别,电话),但它可以包含许多其他字段,开发人员可能不知道,对于表格上的对应值也是如此'FIELD_VALUE'。

PS:我没有将字段标签作为表中的列,因为它们是动态的而不受限制的,并且在前端应用程序中,用户可以根据需要添加新字段。

1 个答案:

答案 0 :(得分:0)

您可以利用动态旋转来获得结果:

SELECT      GROUP_CONCAT(t.line)
    FROM    (
        SELECT      CONCAT('MAX(IF(t.l=''', f.f_label, ''',t.v,NULL)) AS ', f.f_label) AS line
            FROM    field f
        ) AS t
    INTO @dynamic;

SELECT      CONCAT('SELECT t.oi_id, t.oi_price, t.oi_collect_id,', 
            @dynamic, 
            ' FROM ( SELECT oi.*, f.f_label AS l, fv.v_value AS v FROM order_item oi JOIN field_value fv ON fv.oi_fk_id = oi.oi_id JOIN field f ON f.f_id = fv.v_fk_field_id WHERE oi.oi_collect_id = 2 ) AS t GROUP BY t.oi_id;')
    INTO @sql;

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

但受GROUP_CONCAT function限制:

  

结果被截断为group_concat_max_len系统变量给出的最大长度,该变量的默认值为1024.尽管返回值的有效最大长度受到值的约束,但该值可以设置得更高。 max_allowed_pa​​cket的。

编辑 - 为什么需要MAX功能?

要解决给定的问题,我们将根据field表的内容创建动态查询。

对于给定的示例性数据,不使用MAX函数的查询将是:

SELECT      t.oi_id,
            t.oi_price,
            t.oi_collect_id,
            IF(t.l='surname', t.v, NULL) AS surname,
            IF(t.l='name', t.v, NULL) AS name,
            IF(t.l='hobbies', t.v, NULL) AS hobbies,
            IF(t.l='sex', t.v, NULL) AS sex,
            IF(t.l='phone', t.v, NULL) AS phone
    FROM    (
        SELECT      oi.*,
                    f.f_label AS l,
                    fv.v_value as V
            FROM    order_item oi
            JOIN    field_value fv
                ON  fv.oi_fk_id = oi.oi_id
            JOIN    field f
                ON  f.f_id = fv.v_fk_field_id
            WHERE   oi.oi_collect_id = 2
        ) AS t;

哪会导致:

+-------+----------+---------------+---------+-------+----------+------+----------+
| oi_id | oi_price | oi_collect_id | surname | name  | hobbies  | sex  | phone    |
+-------+----------+---------------+---------+-------+----------+------+----------+
|     1 |      100 |             2 | Peter   | NULL  | NULL     | NULL | NULL     |
|     2 |       30 |             2 | Frank   | NULL  | NULL     | NULL | NULL     |
|     5 |      220 |             2 | Nathali | NULL  | NULL     | NULL | NULL     |
|     1 |      100 |             2 | NULL    | Lagaf | NULL     | NULL | NULL     |
|     2 |       30 |             2 | NULL    | Loran | NULL     | NULL | NULL     |
|     5 |      220 |             2 | NULL    | Waton | NULL     | NULL | NULL     |
|     1 |      100 |             2 | NULL    | NULL  | Football | NULL | NULL     |
|     2 |       30 |             2 | NULL    | NULL  | Tennis   | NULL | NULL     |
|     5 |      220 |             2 | NULL    | NULL  | Reading  | NULL | NULL     |
|     1 |      100 |             2 | NULL    | NULL  | NULL     | Male | NULL     |
|     2 |       30 |             2 | NULL    | NULL  | NULL     | Male | NULL     |
|     1 |      100 |             2 | NULL    | NULL  | NULL     | NULL | 12345678 |
|     2 |       30 |             2 | NULL    | NULL  | NULL     | NULL | 11223658 |
+-------+----------+---------------+---------+-------+----------+------+----------+

这是一个中间结果,其中每一行包含一个field的值和其他行的NULL。 MAX函数与GROUP BY子句一起用于以这种方式组合关于一个order item的多行,它选择非空值。它可以被MIN函数替换,它也会使现有值超过null。