有效地包含不在SQL查询的Group By中的列

Eri*_* J. 9 sql sql-server aggregate-functions

特定

表A.

Id   INTEGER
Name VARCHAR(50)
Run Code Online (Sandbox Code Playgroud)

表B.

Id   INTEGER
FkId INTEGER  ; Foreign key to Table A
Run Code Online (Sandbox Code Playgroud)

我希望计算每个FkId值的出现次数:

SELECT FkId, COUNT(FkId) 
FROM B 
GROUP BY FkId
Run Code Online (Sandbox Code Playgroud)

现在我只想输出名称Table A.

这不起作用:

SELECT FkId, COUNT(FkId), a.Name
FROM B b
INNER JOIN A a ON a.Id=b.FkId
GROUP BY FkId
Run Code Online (Sandbox Code Playgroud)

因为a.Name未包含在GROUP BY子句中(产生is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause错误).

重点是从这样的输出转移

FkId  Count
1      42
2      25
Run Code Online (Sandbox Code Playgroud)

输出像这样

FkId  Count  Name
1      42     Ronald
2      22     John
Run Code Online (Sandbox Code Playgroud)

上有SO该错误消息不少比赛,但有些如/sf/answers/451986111/有意见,如"将产生在桌子上3次扫描,而不是1,所以不会结垢".

如何在查询输出中有效地包含联接Table B(与...具有1:1关系FkId)的字段?

mar*_*c_s 12

你可以尝试这样的事情:

   ;WITH GroupedData AS
   (
       SELECT FkId, COUNT(FkId) As FkCount
       FROM B 
       GROUP BY FkId
   ) 
   SELECT gd.*, a.Name
   FROM GroupedData gd
   INNER JOIN dbo.A ON gd.FkId = A.FkId
Run Code Online (Sandbox Code Playgroud)

创建一个CTE(公用表表达式)来处理对您的分组/计数Table B,然后将该结果(每行一行FkId)连接到Table A并将更多列从Table A您的最终结果集中获取.

  • @EricJ.:好吧 - 复制查询,在SQL Server Mgmt Studio中运行它并打开"实际执行计划",你会看到**NO**它将**不执行三次表扫描. ....你链接到的答案中的注释是正确的,因为那里的查询确实**两个额外的**`(SELECT ....)`子查询 - **那些**将每个添加一个表扫描(**不是用于分组的CTE!) (5认同)
  • +1用于使用实际执行计划来诊断性能.:-) (2认同)