0

だから私はテーブルを持っています:

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

これは、個別のクエリと同じカウントを返しました。

主キーとすべてのフィールドがNOTNULLの場合、一意のレコードの数とは異なる合計数になる可能性があることを確認できません。

ところで、これはSybaseASE15にあります。

不一致は50万のうち100かそこらの記録です。他のいくつかのテーブルでもこの​​問題が発生していますが、例として1つだけを選択しました。

編集

完全を期すために、このテーブルをリモートデータベースに完全にコピーする簡単なジョブを作成するときにこの問題を発見したことを言及する必要があります。私のアプリケーションは特定の数の読み取り/書き込み操作を記録していましたが、ソースデータベースのレコード数がターゲットデータベースのレコード数と異なるため、QAに失敗しました。両方の値はCOUNT(*);を介して取得されました。ターゲット(Oracle 10g)から返されたカウントは、私のアプリによって記録された読み取り/書き込み操作の数と同じでした。ソーステーブルのすべてのフィールドがNOTNULLで定義され、主キーが定義されているため、アプリケーションがごく少数のレコードをどのように失っていたかを説明するのに迷いました。

これは、上記の代替クエリを使用し始めたときです。どちらも、アプリの読み取り/書き込みカウントとCOUNT(*)、ターゲットから返された値に同意しました。つまり、一致しなかった唯一の値はCOUNT(*)、ソースデータベース上のでした。

4

3 に答える 3

6

これをサポートするほとんどのデータベースでcount(*)は、実際にすべてのレコードを取得してカウントするわけではありません。代わりに、現在テーブルに格納されている行数(またはおおよその行数)を追跡するメタデータフィールドをフェッチします。一方、実際のデータを操作する必要がある場合、dbmsはとにかく行をフェッチし、期待どおりに行をカウントします。

もちろん、実装方法に関係なく、結果はcount(*)より複雑ですが同等のクエリと同じになると予想するのは合理的です。その場合、(おそらく)テーブルのメタデータが何らかの理由で破損していることを示唆します。(これは良い賭けだと思います-私は特にsybaseに精通していませんが、ほとんどのデータベース管理システムにはテーブルメトリックを強制的に再構築する方法があります...ここで試す価値があるかもしれません)。

もう1つの考えられる説明は、データベースの内部テーブル行カウンターが実際には100%正確になるように設計されていないことです。(この2番目の可能性は、純粋な知識に基づく推測です。これがSybaseの行カウンターに当てはまるかどうかは実際にはわかりませんが、さらに調査する価値があるかもしれません)。

幸運を!

于 2010-12-02T05:08:36.557 に答える
1

私が間違っていなければ、これから判断すると:

を使用する必要がありますselect count(distinct *)select distinct count(*)「それぞれが「」である個別の行を教えてください」と書かれているので、常に1を返すことを期待します。したがって、個別の行の数を示しcount(*)ながら、常に1つの行があります。select count(distinct *)

FWIW、上記はv12.5の場合のようです(違いはわかりませんが)。15.0のドキュメントは次のとおりです。

それは明確に次のように言っています:

count(*)は行数を検索します。count(*)は引数をとらず、distinctと一緒に使用することはできません。null値の存在に関係なく、すべての行がカウントされます。

使用することはできますが、使用することはできselect count(distinct column_1)ませんselect count(distinct *)

于 2010-12-02T03:53:50.617 に答える
1

これは、SybaseASEの質問に対するSybaseASEの回答です。

これは、標準SQL準拠のDBMSに適用されます。他の人には適用されません。

あなたが選んだ答えは正しくありません。

  1. COUNT()ISO / IEC/ANSI標準SQL式です。行を物理的にカウントする必要があります。つまり、大きなテーブルでは低速になります。内部メモリ常駐テーブルまたはカタログテーブル(「メタデータ」)を使用しないようにする必要があります。これは実行時の値であるため、テーブルがアクティブな場合、実行ごとに変更され続けます
  • 角かっこ内に何を配置するかは非常に重要です。

  • COUNT(*)nullを含む行数を返します

  • COUNT(column)columnNotNullである行数を返します

  • はい、の配置DISTINCTも重要です。これにより、作業テーブルが強制的に使用されます。一意でない列をカウントする必要がある場合は、選択の余地はありません。ただし、一意の列の場合は、を使用する必要はありません。DISTINCT

  • DISTINCT列または列から派生した式に適用されます。
    COUNT (DISTINCT *)
    は無意味であり(「すべての列を区別する」)、ASE 15には大幅に改善されたパーサーがあり、そのようなものをキャッチします(以前のバージョンのwoul dhaveは精度の低いエラーメッセージを返しました)。

  • 実際に読み取られる行は、分離レベル(指定されたレベルに対して正しいカウントが返されます)とデータベース上の現在のアクティビティによって異なります。

  • あなたが得ている奇妙な結果を回避する最もクリーンな方法は、使用することです
    COUNT(PK_column)

  • (これはCWであるため)COUNT()存在チェックには、物理​​的に行をカウントするため、いかなる形式も使用しないでください。インデックスのみを使用するため、常にIF EXISTS正しい句を使用してください。WHERE

  1. 正確なカウントが必要であるが、すべての行を読み取りたくない場合は、systabstats各テーブルの行数を含むカタログテーブルを読み取る関数があります。これは、テーブルのサイズに関係なく、瞬時に戻ります。これらの値の最新性は、パフォーマンス、フラッシュ、チェックポイントなどについてサーバーがどのように構成されているかによって異なります systabstats。UPDATESTATISTICSと「flushstats」の2つのコマンドによって、メモリ常駐テーブルから更新されます。これを試して:
    EXEC sp_flushstats
    SELECT ROW_COUNT (DB_ID(), OBJECT_ID("table_name") )

コメントへの回答

このセクションはSybaseとは関係ありません

  1. 他の2つの答えが正しくない理由や、2番目のクエリが予測できない結果を返す理由を説明せずに、問題と主題について明確な説明を提供しました。

  2. これがSybaseASE15.0リファレンス/ビルディングブロックマニュアルCOUNT()121ページ)です。icyrockが誤って引用していることに注意してください。もちろん、誤って解釈していることに注意してください。あなたの出発点は混乱であり、区別の欠如でした。したがって、明確な答えを試みました*DISTINCT

  3. 私はこれをコミュニティWikiにしたので、私の答えは主題に関して完全であり、正規化されているので、あらゆる質問に対する完全な答えとして独立することができますCOUNT()

  4. コメントに応えて、聞いたことがない人にとって、SQLは標準言語であり、1970年代にIBMによって発明され、進歩し、1980年代に次のように標準として受け入れられました。

  • 国際規格機構

  • 国際電気標準会議および(書籍形式)

  • やや遅れて、 American National Standards Institute(Digital Equipment Corpのおかげで無料で公開)によってコピーされました。

  • オープンソースまたはフリーウェアの「SQL」はいずれも標準に準拠していません。これらは、標準のいくつかのコンポーネント(言語構造、機能、コマンド)を提供します。そして、それらが提供するもののうち、標準要件(ACIDトランザクション処理、セキュリティなど)を提供することはめったにありません。

  • 2番目の違いはアーキテクチャであり、SQLを本物の言語として実装することです(一貫性、任意のコードセグメントから呼び出し可能)。コンテキスト切り替えのない単一の本物のマルチスレッドプロセスは、Unixを使用してすべての「マルチスレッド」とコンテキスト切り替えを行う何百ものプログラムの群れと比較することはできません。

  • したがって、SAP / SybaseとDB2(標準に関して厳格)が行うこと、およびMS(実装に関して「柔軟」)が行うことは、(a)標準に準拠しているため(小さなバリエーションについて議論することなく)、(b )彼らは本物のサーバーアーキテクチャを持っており、世界のMySQLやPostgreSQLから光年離れています。その結果、設計されたサーバーの100倍のハードウェア要件が発生します。あなたはあなたが支払うものを手に入れます。

  • Oracleは、商用で一般的であるため特別な場所がありますが、SQLに準拠していません(言語またはACIDトランザクションで、定義を拡張します)。さらに、アーキテクチャがないため、フリーウェアのカテゴリに分類されます。

  • 次に、非標準または反標準のカテゴリがあります。
    MySQL / MyISAMは、特に標準に反するCOUNT()方法で提供します(これは、Leeが提供するMySQL Manualリンクから明らかです。非トランザクションアプリに適しています)。 MySQL / InnoDBおよびBDBは、標準に準拠した方法で提供します。
    COUNT()

  • 大量のマーケティングにもかかわらず、PostgreSQLは最悪です。SQLに準拠していないことに加えて、ACIDトランザクションの概念がなく、「SQL」は言語として実装されていません(コッドの12の規則の規則4)。残念ながら、メジャーリリースごとにSQLの増分が実装されているため、コードを書き直す必要があります。

  • すべてのStandard-SQLベンダーは、Standardに多数の拡張機能を提供しています

  1. 現在のNOT NULL定義が実装される前にテーブルにnull列が含まれていた可能性があるため、テーブル定義内のをすぐに信頼することはできません。それでも、SybaseとDB2は、標準準拠の要件に従って、物理的なスローをカウントします。一連のカウントで証明できます:SELECT COUNT(column_1) from table_name、次にカウントを比較します。

  2. 2番目のクエリは、さらに混乱を招きます。内部テーブルが作成され、データが入力されると、カウントが正確になるためです。期待を込めて作成したので、期待に応えました。しかし、それはその元のテーブルについて何も証明していません。

于 2010-12-13T04:46:22.113 に答える