使用SQL将多个字段合并为一个
时间:2020-03-05 18:45:54 来源:igfitidea点击:
我有三个表tag
,page
,pagetag
与下面的数据
页
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 ...
它将从参数列表中返回第一个非空值。