选择所有资源但需要一行基于每行计算的CSV列

时间:2017-09-28 20:27:24

标签: sql postgresql

问题陈述

我想选择属于某个公司的所有资源,对于每个资源,我想获得它所属的组的逗号分隔列表(使用string_agg)。

数据库关系

Resources
=============================
ResourceId (PK)
CompanyId (FKs to Company)
ResourceName
...
Other columns that are not important

Company
=============================
CompanyId (PK)
...
Other columns that are not important

GroupResources
=============================
GroupId (PK and FKs to Group)
ResourceId (PK and FKs to Resources)

Group
=============================
GroupId (PK)
CompanyId (FKs to Company)
GroupName
...
Other columns that are not important

我目前拥有什么

我目前有两个单独的查询,查询A,它检索我需要的所有信息,除了每个资源的组的聚合,以及查询B,它只检索公司中每个资源的组的聚合。 / p>

查询A

SELECT resources.resourcename, ... other columns that I am selecting out
FROM resources
...
JOINs to tables to get date for some of the other columns
...
WHERE resources.companyid = 1234
ORDER BY resourcename ASC;

查询B

SELECT string_agg(groupname, ',') AS groups
FROM group
JOIN groupresources USING (groupid)
JOIN resources USING (resourceid)
WHERE resources.companyid = 1234
GROUP BY (resourcename)
ORDER BY groups ASC;

我知道使用子查询但在这种情况下,我不太确定如何应用这些知识,因为我似乎正在尝试执行两部分操作(使用{{1等语言)在一次点击中:

  • 获取公司的所有资源
  • 填充每个资源的groups属性

简单地将C#语句添加到查询A将返回公司中所有组的聚合字符串,而不仅仅是资源所属的组。这是一个不正确的假设,我正在制作,请参阅答案了解更多细节。

所需输出

string_agg

1 个答案:

答案 0 :(得分:0)

我假设将string_agg添加到查询A将返回公司中所有组的逗号分隔值列表,而不仅仅是行中资源所属的组正确。< / p>

实际上,向查询A添加string_agg强制使用GROUP BY命令,因为我在聚合函数之外选择了其他列( ...列必须出现在GROUP BY子句中或在聚合函数中使用... )。一旦我将相关列(除聚合列之外的所有内容)添加到GROUP BY子句,我的查询就会按预期运行。

倒数第二个查询

SELECT 
    resources.resourcename, 
    ... other columns that I am selecting out...
    string_agg(groupname, ', ') AS Groups
FROM resources
...
JOINs to tables to get data for some of the other columns
LEFT JOIN groupresources USING (resourceid)
LEFT JOIN group USING (groupid)
LEFT JOIN resources USING (resourceid)
...
WHERE resources.companyid = 1234
GROUP BY 
    resourcename, 
    ...all other columns except the one inside the string_agg function...
ORDER BY resourcename ASC;

GROUP BY确保我获得资源属于的组的结果,而不是公司内的所有组。

...但是这仍然排除了一些行,因为我知道预期的资源数量,而且我的结果还不到这个。

我发现使用SELECT内的JOIN可以达到类似的效果。

最终查询

SELECT 
    resources.resourcename, 
    ... other columns that I am selecting out...
    Groups
FROM resources
...
JOINs to tables to get data for some of the other columns
LEFT JOIN resources USING (resourceid)
LEFT JOIN 
(
    SELECT 
        resourceid, 
        string_agg(groupname,', ' ORDER BY groupname) AS Groups 
    FROM tgroupresources
    JOIN tgroup USING (groupid) 
    GROUP BY resourceid
) AS g USING (resourceid)
...
WHERE resources.companyid = 1234
ORDER BY resourcename ASC;

返回完整的结果集。