我有三个表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
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。尽管如此,如果可能的话,我想要一个独立于数据库供应商的解决方案。
答案 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.id
和group_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 ...
它将从其参数列表中返回第一个非空值。