使用SQL将多个字段连接成一个字段

时间:2008-09-01 10:16:45

标签: sql mysql

我有三个表tagpagepagetag

使用以下数据

ID      NAME
1       page 1
2       page 2
3       page 3
4       page 4

标签

ID      NAME
1       tag 1
2       tag 2
3       tag 3
4       tag 4

pagetag

ID   PAGEID  TAGID
1    2        1
2    2        3
3    3        4
4    1        1
5    1        2
6    1        3

我想在单个查询中获取一个包含每个页面的对应标记名称的字符串。这是我想要的输出。

ID      NAME       TAGS
1       page 1     tag 1, tag 2, tag 3
2       page 2     tag 1, tag 3
3       page 3     tag 4
4       page 4    

这可以用SQL吗?


我正在使用MySQL。尽管如此,如果可能的话,我想要一个独立于数据库供应商的解决方案。

6 个答案:

答案 0 :(得分:3)

是的,你可以通过以下三种方式做到这一点:

SELECT page_tag.id, page.name, group_concat(tags.name)
FROM tag, page, page_tag
WHERE page_tag.page_id = page.page_id AND page_tag.tag_id = tag.id;

尚未经过测试,可能会更有效率地写出来,但应该让你开始吧!

此外,假设MySQL,所以可能不会与MSSQL玩得那么好!并且MySQL对字段名称中的连字符并不狂热,因此在上面的示例中更改为下划线。

答案 1 :(得分:3)

  

Sergio del Amo:

     
    

但是,我没有获得没有标签的页面。我想我需要用左外连接编写我的查询。

  
SELECT pagetag.id, page.name, group_concat(tag.name)
FROM
(
    page LEFT JOIN pagetag ON page.id = pagetag.pageid
)
LEFT JOIN tag ON pagetag.tagid = tag.id
GROUP BY page.id;

不是一个非常漂亮的查询,但应该为您提供所需内容 - pagetag.idgroup_concat(tag.name)null作为您在上面发布的示例中的第4页,但页面应出现在结果中。

答案 2 :(得分:1)

据我所知,SQL92没有定义应该如何进行字符串连接。这意味着大多数引擎都有自己的方法。

如果您想要一个独立于数据库的方法,则必须在数据库之外进行。

(除了Oracle以外的所有版本都未经测试)

<强>的Oracle

SELECT field1 | ', ' | field2
FROM table;

MS SQL

SELECT field1 + ', ' + field2
FROM table;

<强>的MySQL

SELECT concat(field1,', ',field2)
FROM table;

<强> PostgeSQL

SELECT field1 || ', ' || field2
FROM table;

答案 3 :(得分:1)

我得到了一个使用连接的解决方案。查询是:

SELECT
    page.id AS id,
    page.name AS name,
    tagstable.tags AS tags
FROM page 
LEFT OUTER JOIN 
(
    SELECT pagetag.pageid, GROUP_CONCAT(distinct tag.name) AS tags
    FROM tag INNER JOIN pagetag ON tagid = tag.id
    GROUP BY pagetag.pageid
)
AS tagstable ON tagstable.pageid = page.id
GROUP BY page.id

这将是输出:

id   name    tags
---------------------------
1    page 1  tag2,tag3,tag1
2    page 2  tag1,tag3
3    page 3  tag4
4    page 4  NULL

是否有可能以另一种方式提高查询速度?

答案 4 :(得分:0)

我认为您可能需要使用多个更新。

像(未经测试)的东西:

select ID as 'PageId', Name as 'PageName', null as 'Tags'
into #temp 
from [PageTable]

declare @lastOp int
set @lastOp = 1

while @lastOp > 0
begin
    update p
    set p.tags = isnull(tags + ', ', '' ) + t.[Tagid]
    from #temp p
        inner join [TagTable] t
            on p.[PageId] = t.[PageId]
    where p.tags not like '%' + t.[Tagid] + '%'

    set  @lastOp == @@rowcount
end

select * from #temp

丑陋但是。

该示例的T-SQL,但我认为MySql与所使用的所有内容等价。

答案 5 :(得分:0)

  在上面发布的示例中,

pagetag.id和group_concat(tag.name)将为第4页的null,但页面应出现在结果中。

如果需要,可以使用COALESCE函数删除Null:

select COALESCE(pagetag.id, '') AS id ...

它将从其参数列表中返回第一个非空值。