我正在尝试使以下SQL语句正常工作,但出现语法错误:

SELECT A.*, COUNT(B.foo)
FROM TABLE1 A
LEFT JOIN TABLE2 B ON A.PKey = B.FKey
GROUP BY A.*


这里,A是一个有40列的宽表,我想尽可能避免在GROUP BY子句中列出每个列的名称。我有很多这样的表,必须在这些表上运行类似的查询,因此我将不得不编写存储过程。解决此问题的最佳方法是什么?

我正在使用MS SQL Server2008。

#1 楼

SQL中不允许使用GROUP BY A.*

您可以通过使用子查询来对其进行分组,然后在该子查询中进行分组,然后加入:

SELECT A.*, COALESCE(B.cnt, 0) AS Count_B_Foo
FROM TABLE1 AS A
  LEFT JOIN 
      ( SELECT FKey, COUNT(foo) AS cnt
        FROM TABLE2 
        GROUP BY FKey
      ) AS B 
    ON A.PKey = B.FKey ;



SQL-2003标准中有一项功能,允许SELECT列表中的列不在GROUP BY列表中,只要它们在功能上依赖于它们即可。如果该功能已在SQL Server中实现,则您的查询可能被编写为:

SELECT A.*, COUNT(B.foo)
FROM TABLE1 A
LEFT JOIN TABLE2 B ON A.PKey = B.FKey
GROUP BY A.pk                          --- the Primary Key of table A


不幸的是,该功能尚未实现,甚至在SQL中也未实现。 -Server 2012版本-据我所知,不在任何其他DBMS中使用。除了具有此功能的MySQL以外,其他功能都不足够(不足够:上述查询可以工作,但是引擎不会检查功能依赖关系,其他不正确的查询将显示错误的半随机结果)。

@Mark Byers在评论中告知我们,PostgreSQL 9.1添加了为此目的而设计的新功能。它比MySQL的实施更具限制性。

评论


您能提到几个实现了该部分标准的RDBMS吗?我知道,例如,MySQL将允许您(经过适当的设置)在SELECT列表中的GROUP BY子句中包括项目,但对于该值将来自哪一行,它没有定义(因此,如果该列或表达式在功能上不依赖于分组表达式,则它可以来自组中的任何行)。

–亚当·罗宾逊(Adam Robinson)
2012年7月20日15:08

@亚当:不,我不知道没有实现它的RDBMS。如您的评论所述,MySQL拥有它,但不足。

–超立方体ᵀᴹ
2012年7月20日15:10

知道了我实际上是在问是否存在,因为我所拥有的RDBMS经验比我想象中大多数在该站点上回答问题的人要少得多;)但这是我的怀疑。

–亚当·罗宾逊(Adam Robinson)
2012年7月20日15:23

“据我所知,没有其他DBMS。” PostgreSQL 9.1添加了为此目的而设计的新功能。它比MySQL的实施更具限制性。

–马克·拜尔斯
2012年7月21日在7:29



@MarkByers:thnx,我不知道。

–超立方体ᵀᴹ
2012年7月21日在7:31

#2 楼

除了@ypercube的解决方法外,“键入”绝不是使用SELECT *的借口。我在这里已经对此进行了介绍,即使有解决方法,我认为您的SELECT列表仍应包含列名称-即使有大量数字(例如40)。

长话短说,您可以避免通过在对象资源管理器中单击对象的“列”节点并将其拖动到查询窗口中来键入这些大列表。屏幕快照显示了一个视图,但对表也可以执行相同的操作。



但是,如果您想阅读所有应理解的原因,这种将物品拖到几英寸的巨大努力,请阅读我的文章。 :-)

评论


在PostgreSQL(使用EMS SQL Manager)中,我将视图定义为SELECT *,然后从视图定义中复制字段列表。

– dezso
2012年7月20日13:28

我当然同意不要使用SELECT *。不过,我对GROUP BY案件感到好奇。 @Aaron,在“分组依据”列表中有40列是否存在效率问题?

–超立方体ᵀᴹ
2012年7月20日下午13:33

@ypercube-据我所知,如果按A.PK,A.some,A.other,A.columns分组,则实际上并不需要比较语法中所要求的其他某些列。

–马丁·史密斯
2012年7月20日14:09



@datagod对不起,不行,任何差距只能由SSMS开发人员团队来解释。 :-)

–亚伦·伯特兰(Aaron Bertrand)
2012年7月20日14:29

@Pacerier对不起,我完全不同意,但也许您可以详细说明。

–亚伦·伯特兰(Aaron Bertrand)
2015年4月9日15:41