SQL:返回一列,其中包含具有相同值的行数
我有一个从数据库返回系统和区域的查询,如下所示:SQL:返回一列,其中包含具有相同值的行数,sql,sql-server-2008,Sql,Sql Server 2008,我有一个从数据库返回系统和区域的查询,如下所示: SELECT Areas.ID AreaID, Areas.Name AreaName, Systems.* FROM Systems INNER JOIN Areas ON Areas.ID = Systems.AreaID WHERE .... 这将返回如下所示的数据: | AreaID | AreaName | SystemName | ... | 1 | are
SELECT Areas.ID AreaID,
Areas.Name AreaName,
Systems.*
FROM Systems
INNER JOIN Areas ON Areas.ID = Systems.AreaID
WHERE ....
这将返回如下所示的数据:
| AreaID | AreaName | SystemName | ...
| 1 | area1 | sys1 |
| 1 | area1 | sys2 |
| 1 | area1 | sys3 |
| 1 | area1 | sys4 |
| 2 | area2 | sys5 |
| 2 | area2 | sys6 |
我想返回一个额外的列,其中包含返回的每个区域中的系统数,因此我最终得到如下结果:
| AreaID | AreaName | SystemName | noOfSystems | ...
| 1 | area1 | sys1 | 4 |
| 1 | area1 | sys2 | 4 |
| 1 | area1 | sys3 | 4 |
| 1 | area1 | sys4 | 4 |
| 2 | area2 | sys5 | 2 |
| 2 | area2 | sys6 | 2 |
SELECT
a.ID AreaID,
a.Name AreaName,
s1.*,
(SELECT COUNT(s2.SystemName)
FROM Systems s2
WHERE a.id = s2.AreasID) AS noofSystem
FROM Systems s1
INNER JOIN Areas a ON a.ID = S1.AreaID
WHERE ....
即,有4个系统的区域id为1,2个系统的区域id为2
如何做到这一点?我肯定听说有一个内置函数可以实现这一点,但我找不到我想要的功能。使用如下相关子查询:
| AreaID | AreaName | SystemName | noOfSystems | ...
| 1 | area1 | sys1 | 4 |
| 1 | area1 | sys2 | 4 |
| 1 | area1 | sys3 | 4 |
| 1 | area1 | sys4 | 4 |
| 2 | area2 | sys5 | 2 |
| 2 | area2 | sys6 | 2 |
SELECT
a.ID AreaID,
a.Name AreaName,
s1.*,
(SELECT COUNT(s2.SystemName)
FROM Systems s2
WHERE a.id = s2.AreasID) AS noofSystem
FROM Systems s1
INNER JOIN Areas a ON a.ID = S1.AreaID
WHERE ....
或:
SELECT
Areas.ID AreaID,
Areas.Name AreaName,
Systems.SystemName,
COUNT(Systems.SystemName) AS noOfSystems
FROM Systems
INNER JOIN Areas ON Areas.ID = Systems.AreaID
WHERE ...
GROUP BY
Areas.ID AreaID,
Areas.Name AreaName,
Systems.SystemName;
您需要使用聚合函数
COUNT()
,然后使用groupby
。这可以在相关子查询中完成:
SELECT Areas.AreaID AreaID,
Areas.areaname AreaName,
s1.SystemName,
(select count(systemname)
from systems s2
where s1.areaid = s2.areaid
group by areaid) noOfSystems
FROM Systems s1
INNER JOIN Areas
ON Areas.AreaID = s1.AreaID
WHERE ....
看
或者,您可以使用加入的子查询来获取总计数:
SELECT Areas.ID AreaID,
Areas.Name AreaName,
s1.SystemName,
s2.NoOfSystems
FROM Systems s1
INNER JOIN Areas
ON Areas.ID = s1.AreaID
INNER JOIN
(
select COUNT(SystemName) NoOfSystems,
AreaID
from systems
group by AreaID
) s2
on s1.AreaID= s2.AreaID
WHERE ....
看
此版本使用子查询获取总计数,然后将其连接回Systems
表以返回其他列(如果需要)
或者,如果RDBMS具有此选项,则可以使用窗口功能,方法是:
请参见这将为我们提供结果中与当前行具有相同AreaID和AreaName的行数。因为我不确定AreaName是否唯一,所以我将其包括在计数中:
;WITH cte AS (
-- Original query
SELECT Areas.ID AreaID,
Areas.Name AreaName,
Systems.SystemName
FROM Systems
INNER JOIN Areas ON Areas.ID = Systems.AreaID
--WHERE...
)
SELECT AreaID,
AreaName,
SystemName
-- Here's where we get the count of rows returned for each unique area
(SELECT COUNT(*) FROM cte WHERE AreaID = c.AreaID AND AreaName = c.AreaName) AS noOfSystems
FROM cte c
以这种方式使用a将允许我们使用原始查询,而无需对其进行更改。您使用的是哪种DBMS?神谕Postgres?@steinar我不知道你为什么删除sql server 2008标记,它注意到他们使用的数据库窗口函数(count(…)over(…)也存在于其他RDBMS中,例如Oracle查看OP的所需输出,我假设他们希望结果中的行数与当前行具有相同的AreaID和AreaName,不同的系统名。@TimLehner修复了第一个版本,并添加了所有三个查询的演示