8

グループから任意の値を返す集計関数はありますか?MINまたはを使用することもできますMAXが、テキストフィールドであるため、可能であればオーバーヘッドを回避したいと思います。

私の状況はエラーログの要約です。エラーはエラーの種類ごとにグループ化され、グループごとにエラーテキストの例が表示されます。例としてどのエラーメッセージを使用してもかまいません。

SELECT
    ref_code,
    log_type,
    error_number,
    COUNT(*) AS count,
    MIN(data) AS example
FROM data
GROUP BY
    ref_code,
    log_type,
    error_number

MIN(data)100,000のvarchar(2000)値を比較する必要がないようにするには、何に置き換えることができますか?

4

3 に答える 3

4

次のように、MINをKEEPと組み合わせて使用​​できます。

MIN(data) keep (dense_rank first order by rowid) AS EXAMPLE

この背後にある考え方は、データベースエンジンがVARCHAR(2000)値ではなく、ROWIDを介してデータを並べ替えることです。これは、理論的にはより高速であるはずです。ROWIDを主キー値に置き換えて、より高速かどうかを確認できます

于 2013-01-09T03:08:30.510 に答える
3

提案された答えを見ると、MIN(data)(またはMAX(data))が私が望むものを達成するための最速の方法であるように見えます。不必要に最適化しすぎています。

このデータベースにアクセスしている間に出てくる他の答えを試してみますが、それまでの間、これが一番上に出てきます。

皆様のご尽力に感謝します!

于 2013-01-10T01:09:17.790 に答える
2

さて、OVER PARTITION AND ORDER BYについて質問したので、以下はGROUP BYを実行するバージョンですが、ROW_NUMBER()とOVERおよびPARTITION AND ORDER BYを使用して、最初のref_code, log_type, error_num組み合わせに行番号1( 1)にあるデータ列を使用します。次に、1から始めて、ref_code, log_type, error_num見つかった次の個別の組み合わせで番号を付け直します(そこにあるデータ列を使用して)。したがって、行番号1のデータフィールドを、特定のの代表的なデータフィールドとして単純にプルできますref_code, log_type, error_num

それはまだ何かが欠けています。ダブルパスがない場合は、よりエレガントになります(1回は集計用、もう1回はrow_number()用)。ただし、それでも非常にうまく機能する可能性があります。ダブルパスをなくすことができるかどうかを確認するために、もう少し考えなければなりません。

ただし、大きなデータフィールドの比較は回避されます。そして、それはあなたが求めたことを実行する方法を表しています:集約されたフィールドと相関してデータフィールドから1つの代表的なサンプルを引き出すこと。

SELECT
    t.ref_code,
    t.log_type,
    t.error_number,
    t.count,
    d.data
FROM
(
    SELECT
        ref_code,
        log_type,
        error_number,
        COUNT(*) as count
    FROM data
    GROUP BY
        ref_code,
        log_type,
        error_number
) t
INNER JOIN 
(
    SELECT
        ref_code,
        log_type,
        error_number,
        data,
        ROW_NUMBER() OVER
        (
            PARTITION BY
                ref_code,
                log_type,
                error_number
            ORDER BY
                ref_code,
                log_type,
                error_number
        ) as row_number
    FROM data
) d on
    d.ref_code = t.ref_code and
    d.log_type = t.log_type and
    d.error_number = t.error_number and
    row_number = 1

最後の警告:これを試すためのOracleがありません。しかし、私はOracleのドキュメントを読んでそれをまとめました。


COUNT(*)用にしかなかったGROUP BYを削除する方法をさらに考えた後、以下を追加しました。でもそれがもっと速いかどうかはわかりません。

SELECT *
FROM
(
    SELECT
        ref_code,
        log_type,
        error_number,
        data,
        ROW_NUMBER() OVER
        (
            PARTITION BY
                ref_code,
                log_type,
                error_number
            ORDER BY
                ref_code,
                log_type,
                error_number
        ) as row_number,
        COUNT(*) OVER
        (
            PARTITION BY
                ref_code,
                log_type,
                error_number
            ORDER BY
                ref_code,
                log_type,
                error_number
        ) as count 

    FROM data
) t
WHERE row_number = 1
于 2013-01-09T05:58:03.000 に答える