- ベストアンサー
Accessでデータを「間引き」するには?
Microsoftアクセスを使って電力使用量を管理するシステムを製作しています。 集計する基となっているデータは (1)CSVで出力されたファイル (2)縦に時間が30秒刻みで入力(0:00:00~23:59:30) (3)横にそれぞれの計測機器での計測値が入力 (4)1日1ファイルが生成され、日時を含んだファイル名で保存される 上の様なデータをアクセス上で管理&集計してグラフ化などを行いたいと考えています。 現状で機器が約100個あるので100列、30秒刻みで24時間なので2880行、1日で約300,000ものレコードが生成されています。 データの計測と出力はとあるメーカーの機器で行っているため、容易に仕様を変更することは出来ません。 このままだと長期使用を考えた際にデータ量が大きくなってしまうので、業務上必要なレベルまで集計して、外部ファイルとして保存し必要な際に取り込むという手法を検討中です。 具体的には、現在の30秒間隔でのデータを1分または2分間隔まで間引きしたいと考えています。 このデータを1ヶ月単位でまとめ外部ファイルに出力し、必要な際に取り込ませます。 それぞれのデータは30秒間隔の差分なので、1分または2分にまとめるには2行または4行分のレコードの和算をしなければなりません。 1日単位で出力されたデータを1ヶ月単位でまとめるのは単純に追加クエリを使って可能ですが、上記の様な集計は可能なのでしょうか? 1分間隔ならば、「時間」フィールドの「分」の桁まで一致するレコードをグループ化という方法もあるかと考えましたが「時」の桁が 1桁の場合(0時~9時まで)と2桁の場合(10時以降)があるので、上から○桁目まで一致するものをグループ化して合計を出すという方法も使えません。 (そもそもそんなグループ化の手段があるかどうか知りませんが...) 何かよい方法はありますでしょうか? よろしくお願いいたします。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
おやりになりたいことは2分単位に丸めるという計算ですね 丸めの一般式は Int(数字/基数)*基数 です この式で基数を2分にしてやればいいいのです Int([時間]/#0:02:00#+0.00000001)*#0:02:00# ただし、これでは >一部5レコードと3レコードになってしまう部分がありますね。 こういう現象が出ます これは日付時刻型というのが浮動小数点型の数値であることから生じる現象です 小数点型の数値はすぐに無限小数になってしまいますが コンピュータではこれを有限のデータ型で扱う必要から丸めることになり そのときに生じるわずかな誤差がInt関数を使用することにより大きく現れてしまうのです これに対処すには丸めで生じるわずかな誤差分を補正してやります Int([時間]/#0:02:00#+0.00000001)*#0:02:00#
その他の回答 (4)
#2、#3です。 Int(CCur(Nz([時刻]*24*30,0))) Nzを使用して良いのですか?Nullが0でくくられては困るように感じるのですが。実際の仕様が判らないので何とも云えませんが。 それと誤差丸めにCCurを使用するのは(好みの問題ですが)私ならば使いません。#2、#4に提示されたような方法が、何が起きているか明快なので、問題が発生したときデバッグが楽です。
お礼
丸めて算出する部分は時刻を表すフィールドのみなのでNullが入ることはありません。そうなるとこれでも問題は無い様ですね。 ですがご指摘からするとCCurは後のことを考えると使わない方が良いみたいですね。 +0.00000001の様にアナログ的に対処するよりも関数で対処した方が良いものかとずっと思っていましたが単純にそうではないという事を認識しました。 大変ありがとうございました。
#2です >このクエリでは時刻フィールドをどのような数字と捉えて演算をしているのでしょうか クエリというかアクセス(そして多くのDBや言語)の日付時刻型の実体は、倍精度ぐらいの数字です。整数部が日付、小数部が時分秒以下を表現します。で Int([時刻]*24*30) のような発想が出ます。しかし少数で「分」を正確に表現できないため、 >一部5レコードと3レコード が発生するようですね。Int([時刻]*24*30+0.1) みたいな対策では如何でしょうか?
補足
ご返答ありがとうございます。 なるほど、日付以下を小数としていたんですね。 Int関数による小数値の誤差発生に関しては聞いたことがありました。 現在ご教授頂いた方法を参考に以下のような形で対処したのですがこれは問題は無いでしょうか? ちなみに結果は正しく表示されております。 V: Int(CCur(Nz([時刻]*24*30,0)))
時間フィールドは「日付時刻型」でしょうか?そうでなければフィールドを追加し型を変換してください。SQL文は UPDATE 時刻 SET 時刻.時刻 = [時刻文字]; みたいなので。で、日付時刻型であれば Int([時刻]*24*30) AS T のごとくすれば2分間隔で表示できます。下記のようなSQL文で確認しました。 SELECT 時刻.時刻文字, Int([時刻]*24*30) AS T FROM 時刻;
補足
ありがとうございます。 時間フィールドは日付時刻型になっております。 実際に試してみました。 たしかに4レコード毎に同じ数字が振られるようになりましたが、一部5レコードと3レコードになってしまう部分がありますね。 Int関数の影響でしょうか。 このクエリでは時刻フィールドをどのような数字と捉えて演算をしているのでしょうか?
- CHRONOS_0
- ベストアンサー率54% (457/838)
方法はあります 具体的なやり方を提示するには時間フィールドがどうなっているかの 詳しい情報が必要ですね >0:00:00~23:59:30 こういう文字列が入っているのですか あるいは 0:00:00 23:59:30 のような文字列?
補足
ありがとうございます。 時間フィールドは日付時刻型になっており、後者の[0:00:00]の様な文字列が挿入されています。 この様なレコードが2880件存在する形になります。
お礼
ご返答ありがとうございます。 なるほど、一般的にはのようにして丸めるのですね。 他にも応用出来ますね!とても参考になりました。 実際にこの方法を使ってみたいと思います。 小数値の誤差発生に関しては聞いたことがありました。