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的实施更具限制性。
#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
评论
您能提到几个实现了该部分标准的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