我需要计算一个表的行,但我提示有一个不寻常的count(*)行为。
当我在空表上使用多列选择时,count(*)不返回结果。但是如果我从select语句中删除其他列(单列Select),则返回预期结果(0行)。
在下面的代码中,您将找到多个测试来向您展示我正在谈论的内容。
以下代码的结构是:
1)创建表格
2)空表测试的多列选择,返回意外结果
3)空表测试单列选择,返回预期结果
4)填充表测试的多列选择,返回预期结果
题
鉴于此结果,我的问题是:
为什么空表上的多列选择不返回0,并且单列选择返回它?
预期结果定义
对我的预期结果意味着:
如果表为空,则count(*)返回0。
如果表不为空,则count返回行计数
- 评估测试表
CREATE TABLE #EMPTY_TABLE(
ID INT
)
DECLARE @ID INT
DECLARE @ROWS INT
--MULTI COLUMN SELECT WITH EMPTY TABLE
--assignment attempt (Multi-column SELECT)
SELECT @ID = ID, @ROWS = COUNT(*)
FROM #EMPTY_TABLE
--return Null instead of 0
SELECT @ROWS Test_01 , ISNULL(@ROWS, 1 )'IS NULL'
--Set variable with random value, just to show that not even the assignment is happening
SET @ROWS = 29
--assignment attempt (Multi-column SELECT)
SELECT @ID = ID, @ROWS = COUNT(*)
FROM #EMPTY_TABLE
--return 29 instead of 0
SELECT @ROWS Test_02
--SLELE COLUMN SELECT EMPTY TABLE
--assignment attempt (Single-column SELECT)
SELECT @ROWS = COUNT(*)
FROM #EMPTY_TABLE
--returns 0 the expected result
SELECT @ROWS Test_03
--MULTI COLUMN SELECT with FILLED TABLE
--insert a row
INSERT INTO #EMPTY_TABLE(ID)
SELECT 1
--assignment attempt
SELECT @ID = ID, @ROWS = COUNT(*)
FROM #EMPTY_TABLE
--Returns 1
SELECT @ROWS Test_04
所以我阅读了sybase的分组机制,并得出结论,在你的查询中你有一个“Transact-SQL扩展列”(参见:docs on group by下的Usage - > Transact-SQL扩展来分组和拥有):
包含聚合的选择列表可以包括不是聚合函数的参数且不包含在group by子句中的扩展列。扩展列会影响最终结果的显示,因为会显示其他行。*(强调我的)
(关于*:这个最后一个语句在你的具体情况下实际上是错误的,因为一行变成零行)
也可以在docs on group by下使用 - >如何分组和查询聚合工作,你会发现:
group by子句为表中的每个唯一值将剩余的行收集到一个组中。省略组为整个表创建一个组。 (强调我的)
基本上:
COUNT(*)
将触发整个查询成为聚合,因为它是一个聚合函数(导致隐式GROUP BY NULL
)SELECT
子句中添加ID,然后将第一组(由无行组成)扩展到其包含的行(无)中,并将其与聚合结果列连接在一起。在你的情况下:计数是0,因为你也查询id,对于每个id,将生成一个附加计数的行。但是,由于您的表没有行,因此没有任何结果行,因此没有分配。 (一些示例在链接的文档中,因为没有id,并且现有的id必须在结果的id列中,...)
总是得到计数,你应该只有SELECT @ROWS = COUNT(*)
和分别选择ID。
如果你在计算行数并且在没有行时尝试获取ID - 你需要检查它们是否存在。像这样的东西:
SELECT COUNT(*),
(CASE WHEN EXISTS(SELECT ID FROM EMPTY_TABLE) THEN (SELECT ID FROM EMPTY_TABLE) ELSE 0 END) AS n_id
FROM EMPTY_TABLE
如果超过1行,您将收到子查询错误。
这个查询:
SELECT @ID = ID, @ROWS = COUNT(*)
FROM #EMPTY_TABLE
问题是COUNT(*)
使这成为一个聚合查询,但你也想返回ID
。没有GROUP BY
。
我怀疑你的最终问题是你忽略了这些错误。
This SQL Fiddle使用SQL Server(类似于Sybase)。但是,失败是非常普遍的,并且由于查询在几乎任何数据库中都不起作用。