为什么GROUP BY语句中的通配符不起作用?


29

我正在尝试使以下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 Server 2008。

Answers:


32

GROUP BY A.* 在SQL中是不允许的。

您可以通过使用子查询来对它进行分组,然后再联接:

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的MySQL之外,其他都没有(不足为:上述查询可以工作,但是引擎不会检查功能依赖关系,其他写得不好的查询将显示错误的半随机结果)。

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


您能提到几个实现了该标准部分的RDBMS吗?我知道,例如,MySQL将让你(给予适当的设置),包括不在内的物品GROUP BY在条款SELECT清单,但它留下它不确定哪个行该值将来自(所以如果列或表达式ISN在功能上不依赖于分组表达式,那么它可以来自组内的任何行)。
亚当·罗宾逊

@Adam:不,我不知道没有实现它的RDBMS。如您的评论所述,MySQL有此功能,但功能不足。
ypercubeᵀᴹ

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

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

@MarkByers:thnx,我不知道。
ypercubeᵀᴹ

24

除了@ypercube的变通办法之外,“键入”绝不是使用的借口SELECT *。我在这里已经写过有关此内容的信息,即使有解决方法,我认为您的SELECT列表仍应包含列名-即使有大量的数字(如40)。

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

在此处输入图片说明

但是,如果你想了解的所有原因,为什么你应该服从自己这个巨大的拖动某一项几英寸的努力程度,请阅读我的文章。:-)


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

我当然同意SELECT *不应使用。我对此很好奇GROUP BY。@Aaron,在“分组依据”列表中有40列是否存在效率问题?
ypercubeᵀᴹ

1
@ypercube-据我所知,如果按其分组A.PK, A.some, A.other, A.columns并没有麻烦,实际上some, other, columns只是语法需要比较 。
马丁·史密斯

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

1
@Pacerier对不起,我完全不同意,但也许您可以详细说明。
亚伦·伯特兰
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.