SQL将多行转换为可变长度的单行

时间:2011-02-11 03:55:48

标签: php sql mysql

我正在使用MySQL(以及可选的PostgreSQL)为drupal6 / PHP5编写模块。

我有一个MySQL表字段(fid,名称,类型,类......)和一个参数表 引用这些字段的值(lid,pid,fid,numval,stringval)(通过“fid”)。 参数只有数值(FLOAT / REAL)或字符串值(TEXT),但不是 两者(根据字段“类型”)。

对于给定的“盖子”,我可以有多个/可变数量的参数/行 很容易在循环中检索为行。我想做的是找回一个 “值”行,其中每列都有相关的字段名称作为其标题。 在drupal中,这样的查询将返回所有字段:值对作为对象属性:值 在单个数据库调用中配对,我认为这样会更有效。

谷歌找到了一些SQL示例“将多行合并为一行”,但是 他们似乎假设预定标记了固定数量的列/字段 结果集和/或将列条目构建为单个复合“name:value”字符串。 我希望可能有一个更通用的方法来处理任意数量的 字段,适用于MySQL和PostgreSQL?

我只有非常基本的SQL经验,因此我不知道有关视图或临时表或动态定义和执行过程的可能性。

感谢。

举例来说

FIELDS
FID    NAME       TYPE  CLASS      WIDGET   SIZE   UNITS  DESCRIPTION  .....
 1     voltage   float  instrument   text   10
 2     current   float  instrument   text   10
 3     size      float  sample       text   10
 4     colour    text   sample       text   30
 ...

PARAMS
PID  LID   FID  NUMVAL   STRINGVAL
 1    1     1     2.5      NULL
 2    1     4     NULL    'blue' 
 3    2     1     2.7      NULL
 4    2     2     13       NULL
 5    2     3     27       NULL
 6    2     4     NULL     'greenish blue'

使用一些选择LID = 1的表达式返回单行:

|  voltage  |  colour |
-----------------------
|    2.5    |  'blue' |

并选择LID = 2

|  voltage  | current | size |    colour       |
------------------------------------------------
|    2.7    |  13     |  27  | 'greenish blue' |   

2 个答案:

答案 0 :(得分:0)

这会垂直而不是水平显示数据。

SELECT
    FIELDS.NAME AS PROPERTYNAME,
    CASE WHEN PARAMS.NUMVAL IS NULL THEN STRINGVAL ELSE CAST(PARAMS.NUMVAL AS VARCHAR(100)) END AS PROPERTYVALUE
FROM
    PARAMS, FIELDS
WHERE
    PARAMS.FID = FIELDS.FID
        AND
    PARAMS.LID = 1
ORDER BY
    PARAMS.FID

SQL可能需要一些调整,但如果不访问您的数据库架构,这是我能做的最好的事情。

答案 1 :(得分:0)

数据透视表的东西似乎太乱了。 我想要用这样简单的东西去做 (感谢John Pick向我展示了如何使用CASE!):

SELECT p.l_id, 
   GROUP_CONCAT(
       CONCAT(f.name,'=', 
          CASE WHEN p.stringval IS NULL
               THEN p.numval 
            ELSE p.stringval 
          END
       ) SEPARATOR '||'
   ) AS vals 
 FROM
    params AS p 
 LEFT JOIN fields AS f 
    ON  p.f_id=f.f_id 
 WHERE 
    p.l_id=1 
 GROUP BY 
    p.l_id;

并在PHP中使用explode()对“vals”字符串进行后处理。

+------+---------------------------------------------------------- ... -+
| l_id | vals                                                           |
+------+---------------------------------------------------------- ... -+
|    1 | kv=50||ma=50||pressure=0||temp_ccd=-58||temp_sample=150|| ...  |
+------+---------------------------------------------------------  ...  +

出了什么警察!我希望给出一个更优雅的解决方案 以正确的格式返回列所需的所有信息 存在于PARAMS和FIELDS表中。而现在我不得不担心字符串 其中包含SEPARATOR: - /