如何选择列值作为列名称并将结果分组为行

时间:2012-02-27 08:34:56

标签: php mysql

如何选择列值作为列名称并将结果分组为行。

我有一张桌子:

id      articleId   label           value
1       1           title           Example title
2       1           description     This is the description
3       1           author          Me
4       2           title           Example of another type of article
5       2           description     Short description
6       2           author          Someone else

是否可以选择所有行并使用标签作为列名称,将值作为该列名称的值,然后按文章名称对它们进行分组。 所以我想如何让它返回:

articleId   title           description     author
1           Example title   This is the..   Me
2           Example of an.. Short descr..   Someone else

我将其用于CMS,用户可以在其中定义文章的字段,因此我们不必自定义表格。这就是为什么我没有制作表格,因为我想让它返回。我也知道我可以在php中轻松地将结果转换为此。

- 编辑 -

这可以在不知道添加了什么标签的情况下完成吗?在这个例子中我使用标题,描述和作者。但它很可能是完全不同的东西,如title,shortDescription,availableTo,techInformation等。这个想法是文章是为用户定制的,无需更改数据库和查询

3 个答案:

答案 0 :(得分:1)

您可以使用数据透视表技巧 -

SELECT
  articleId,
  MAX(IF(label = 'title', value, NULL)) AS title,
  MAX(IF(label = 'description', value, NULL)) AS description,
  MAX(IF(label = 'author', value, NULL)) AS author
FROM
  table
GROUP BY
  articleId

答案 1 :(得分:1)

我想我最好发布一个答案,即使不是OP希望听到的。您要做的是根据列label中的不同值填充具有可变数量列的查询,所有这些都与articleID相关联。以您的具体示例为例,以下是我最有可能在此实例中进行的结果查询(尽管来自@Devart的示例同样有效)

SELECT
    t.id,
    t.articleId,
    t1.value AS title,
    t2.value AS description,
    t3.value AS author

FROM `tableName` t
LEFT JOIN `tablename` t1
    ON t1.article_id = t.article_id AND t1.label = 'title'
LEFT JOIN `tablename` t2
    ON t2.article_id = t.article_id AND t2.label = 'description'
LEFT JOIN `tablename` t3
    ON t3.article_id = t.article_id AND t3.label = 'author'

现在将此扩展为最多 n 标签,我们得到以下查询(包含元代码,此查询不会逐字执行)

SELECT DISTINCT label FROM `tableName`;

SELECT 
    t.id,
    t.articleId
    // for (i=1;i<= number of distinct labels) {
    ,t[i].value AS [value[i]]
    // }

FROM `tableName` t
// for (i=1;i<= number of distinct labels) {
LEFT JOIN `tablename` t[i]
    ON t[i].article_id = t.article_id AND t[i].label = [value[i]]
// }
;

所以你能做的就是以下之一。

  1. SELECT t.* FROM tablename t然后根据需要进行PHP处理
  2. SELECT DISTINCT label FROM tablename并让PHP使用许多LEFT JOIN s(或MAX / GROUP BY逻辑构建第二个查询,如果愿意的话)
  3. 创建存储过程以执行与#2相同的操作。这很可能比#2更有效,但整体效率可能低于#1。

答案 2 :(得分:0)

尝试以下:

 select t1.articleId,t1.title,t1.description,t1.author 
 from tablename as t1 
 left join (select max(articleId) as articleId 
           from tablename 
           group by articleId   ) as t2
 on t1.articleId=tsm.articleId where [.....]