我需要计算表的行数,但提示我有count(*)异常行为。
当我在空表上使用多列选择时,count(*)不返回结果。但是,如果我从select语句(单列Select)中删除其他列,则会返回预期结果(0行)。
在下面的代码中,您将找到多个测试来向您展示我在说什么。
以下代码的结构为:
1)创建表格
2)在空表测试中选择多列,这将返回意外结果
3)在空表测试中选择单列,这将返回预期结果
4)在填充表测试中选择多列,它返回预期结果
问题
鉴于此结果,我的问题是:
为什么在空表上的多列选择不返回0,而单列选择却返回0?
预期结果定义
对我来说,预期结果意味着:
如果表为空,则count(*)返回0。
如果表不为空,则计数返回行计数
-创建测试表
CREATE TABLE #EMPTY_TABLE(
ID INT
)
DECLARE @ID INT
DECLARE @ROWS INT
-带空表的多列选择
--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
-带空表的单列选择
--assignment attempt (Single-column SELECT)
SELECT @ROWS = COUNT(*)
FROM #EMPTY_TABLE
--returns 0 the expected result
SELECT @ROWS Test_03
-带填充表的多列选择
--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
答案 0 :(得分:4)
因此,我阅读了sybase的分组机制,并得出结论,在您的查询中,您具有“ Transact-SQL扩展列”(请参见:用法-> Transact-SQL扩展下的docs on group by以分组并具有):
包含聚合的选择列表可以包含扩展列,这些扩展列不是聚合函数的参数,也不包含在group by子句中。扩展列会影响最终结果的显示,因为会显示其他行。* (强调我的意思)
(关于*:这最后一条语句在您的特定情况下实际上是错误的,因为一行变成了零行)
还可以在docs on group by的“用法”->“如何按分组进行汇总以及如何查询聚合”中找到
group by子句针对group by表达式中的每个唯一值将剩余的行收集到一组中。 省略分组依据为整个表格创建一个分组。 (强调我的)
从本质上说:
COUNT(*)
会触发整个查询为一个聚合,因为它是一个聚合函数(导致隐式GROUP BY NULL
)SELECT
子句中添加ID,然后将第一个组(无行)扩展到其包含的行(无),并将其与合计结果列连接在一起。在您的情况下:计数为0,因为您还要查询id,所以对于每个id,都会生成一行,该计数将附加到该行。但是,由于表没有行,因此没有结果行,因此也没有赋值。 (某些示例在链接的文档中,并且由于没有ID,并且现有ID必须在结果的ID列中,...)
要始终获取计数,您可能应该只SELECT @ROWS = COUNT(*)
并分别选择ID。
答案 1 :(得分:0)
如果要统计行数并尝试在没有行的情况下获取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,则会出现子查询错误。
答案 2 :(得分:0)
此查询:
SELECT @ID = ID, @ROWS = COUNT(*)
FROM #EMPTY_TABLE
问题是COUNT(*)
使其成为聚合查询,但是您还想返回ID
。没有GROUP BY
。
我怀疑您的最终问题是您忽略了此类错误。
This SQL Fiddle使用SQL Server(与Sybase类似)。但是,失败是非常普遍的,并且是由于查询在几乎所有数据库中均不起作用。