使用SQL将多个字段合并为一个

时间:2020-03-05 18:45:54  来源:igfitidea点击:

我有三个表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

页面标签

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。尽管如此,如果可能的话,我希望有一个独立于数据库供应商的解决方案。

解决方案

回答

是的,我们可以跨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对字段名中的连字符并不陌生,因此在上面的示例中将其改为下划线。

回答

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

类似于(未经测试)的内容:

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具有与所使用的所有功能等效的功能。

回答

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

如果要使用独立于数据库的方法,则必须在数据库外部进行。

(除Oracle以外的所有产品都未经测试)

甲骨文

SELECT field1 | ', ' | field2
FROM table;

微软SQL

SELECT field1 + ', ' + field2
FROM table;

的MySQL

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

PostgeSQL

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

回答

Sergio del Amo:
  
  
    However, I am not getting the pages without tags. I guess i need to write my query with left outer joins.
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;

这不是一个非常漂亮的查询,但是应该给我们我们想要的内容,在我们上面发布的示例中,第4页的" pagetag.id"和" group_concat(tag.name)"将为" null",但该页面应显示在结果。

回答

我有一个解决方案与联接一起玩。查询是:

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

是否有可能以其他方式提高查询速度?

回答

pagetag.id and group_concat(tag.name) will be null for page 4 in the example you've posted above, but the page shall appear in the results.

如果需要,我们可以使用COALESCE函数删除Null。

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

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