SELECT COUNT(*)如何与表中所有记录的计数不同?

时间:2010-12-02 03:39:50

标签: sql select sybase-ase

所以我有一张桌子:

CREATE TABLE TABLE_NAME (
    COLUMN_1   char(12)    NOT NULL,
    COLUMN_2   char(2)     NOT NULL,
    COLUMN_3   char(1)     NOT NULL,
    COLUMN_4   int         NOT NULL,
    COLUMN_5   char(2)     NOT NULL,
    COLUMN_6   money       NOT NULL,
    COLUMN_7   smallint    NOT NULL,
    COLUMN_8   varchar(10) NOT NULL,
    COLUMN_9   smallint    NOT NULL,
    COLUMN_10  datetime    NOT NULL
    Primary Key (COLUMN_1, COLUMN_2, COLUMN_3)
)

SELECT COUNT(*)返回的值不同于SELECT DISTINCT COUNT(*)。怎么可能呢?

我也试过

SELECT COUNT(*) FROM (
    SELECT
        COLUMN_1,
        COLUMN_2,
        COLUMN_3,
        COLUMN_4,
        COLUMN_5,
        COLUMN_6,
        COLUMN_7,
        COLUMN_8,
        COLUMN_9,
        COLUMN_10
     FROM TABLE_NAME
    ) TMP

返回与不同查询相同的计数。

我有点累了,所以我希望我不会遗漏一些明显的东西,但是我看不到主键如何以及所有字段都是NOT NULL,总计数可能不同于独特的记录。

BTW,这是在Sybase ASE 15上。

差异是一百个左右的记录。我也在其他几个表中看到了这个问题,但只选择了一个例子。

编辑:

为了完整起见,我应该提一下,在编写一个简单的工作来将此表完全复制到远程数据库时,我发现了这个问题。我的应用程序记录了一定数量的读/写操作,但QA失败,因为源数据库中的记录数与目标数据库中的记录数不同。这两个值都是通过COUNT(*)获得的;从目标返回的计数(Oracle 10g)与我的应用程序记录的读/写操作数相同。由于源表上的所有字段都定义为NOT NULL并且定义了主键,因此我无法解释我的应用程序如何丢失少量记录。

这是我开始使用上面列出的备用查询时,这两个查询都同意我的应用程序读/写计数,以及从目标返回的COUNT()值。换句话说,唯一不匹配的值是源数据库上的COUNT()。

3 个答案:

答案 0 :(得分:6)

在大多数支持它的数据库中,count(*)实际上并不检索所有记录并对它们进行计数 - 而是取出一些元数据字段,它只跟踪当前存储的行数(或近似行数)桌子。另一方面,当你做一些需要处理实际数据的事情时,dbms仍然会获取行,并且它会按照你的预期计算它们。

当然,无论如何实现,count(*)的结果与更复杂但等效的查询相同,都是合理的。那表明,(可能)你的表的元数据以某种方式被破坏了。 (我会说这个是一个不错的选择 - 我不熟悉sybase,但大多数dbms都有办法强制重建表指标......这可能值得一试)。

另一种可能的解释是,数据库的内部表行计数器实际上并未设计为100%准确。 (第二种可能性是纯粹受过教育的猜测......我实际上并不知道Sybase的行计数器是否属实,但可能值得进一步调查)。

祝你好运!

答案 1 :(得分:1)

如果我没弄错的话,从这个判断:

你应该使用select count(distinct *)。我希望select distinct count(*)总是返回1,因为它说“给我不同的行,每个行都是count(*)”,因此总会有一行,而{{1} }给出了不同行的计数。

FWIW,以上似乎是针对v12.5(虽然我没有看到任何差异),这里是15.0文档:

明确说明如下:

  

count(*)查找行数。 count(*)不带任何参数,不能与distinct 一起使用。无论是否存在空值,都会对所有行进行计数。

您可以使用select count(distinct *)左右,但不能使用select count(distinct column_1)

答案 2 :(得分:1)