我是Oracle的新手。 卡在下面: 我有以下2个表:
网站:
**SiteID|SiteName**
1 Sydney
2 Newyork
3 Delhi
人
**RecordID|PeopleID|SiteID**
1 1 1
2 1 2
3 2 2
4 3 1
5 3 2
6 3 3
现在在我的查询中我想要一个像这样的输出:
**PeopleID | AssignedSites**
1 Sydney,NewYork
2 Newyork
3 Sydney,NewYork,Delhi
- 解决方案应该在Oracle 10g以及11g中运行。
- 为了简洁,我在上面的例子中给出了一小部分数据。但是,在我的prod场景中,一个人可以与1000多个位置相关联,并且可能有1000多个这样的人,所以解决方案不应该打破情况下!
任何帮助都将受到高度赞赏。
提前致谢。
答案 0 :(得分:3)
尝试使用XMLAGG
,如下所示:
select
p.PeopleID,
rtrim(xmlagg(xmlelement(e, s.SiteName, ',')).extract('//text()').getclobval(), ',')
from people p
join site s on p.SiteID = s.SiteID
group by p.PeopleID;
如果您需要以特定顺序连接,例如增加SiteId的顺序,则在xmlagg中添加order by
子句:
select
p.PeopleID,
rtrim(xmlagg(xmlelement(e, s.SiteName, ',')
order by s.SiteId).extract('//text()').getclobval(), ',')
from people p
join site s on p.SiteID = s.SiteID
group by p.PeopleID;
如果您想要分配给网站100的所有人的显示结果:
select p.PeopleID,
rtrim(xmlagg(
xmlelement(e, s.SiteName, ',') order by s.SiteId
).extract('//text()').getclobval(), ',')
from people p
join site s on p.SiteID = s.SiteID
join (
select distinct PeopleID
from people
where siteID = 1
) p2 on p.PeopleID = p2.PeopleID
group by p.PeopleID;
答案 1 :(得分:2)
评论太长了。
listagg()
是显而易见的选择,但它在Oracle 10中不可用。但是,即使在Oracle 11中,listagg()
仅限于长度为4,000的字符串,并且您明确说出"人可以与1000多个地点相关联,并且#34;。
有很多方法可以解决这个问题,使用CLOB,XML,以及毫无疑问的其他解决方案。但是,有多少使用成千上万个字符的位置列表?如此多的位置,您将无法将结果放在标准的varchar2()
字段中。
或许用这种方式在数据库中总结它们并不是解决实际问题的最佳方法。
答案 2 :(得分:1)
我认为我很接近它,只需要一个小帮助:我创建了一个函数GetSiteName,它返回SiteID的站点名称。现在我使用下面的xmlagg,我需要调用这个函数GetSiteName:
select PeopleID, rtrim (xmlagg (xmlelement (e, clint.GetSiteName(SiteID) || ',')).extract ('//text()'), ',') SITEIDS
from client.People group by PeopleID;/
基本上需要帮助从xmlagg内部调用函数,有什么想法吗?
答案 3 :(得分:0)
我只需要在oracle 10g上使用listagg的替代方法,并在此页https://oracle-base.com/articles/misc/string-aggregation-techniques中找到一个。
只需使用wm_concat,虽然它不受oracle支持并且已在12c中下载。
以上示例:
select
p.PeopleID,wm_concat(s.SiteName)
from people p
join site s on p.SiteID = s.SiteID
group by p.PeopleID;