質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.60%

VBSでレコードの重複排除をしたい

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,491

amatsuno

score 40

VBSでレコードの重複排除をしたいと思っていおります

現在、レコードとして
date3,user,u_id,action
2019/04/06 20:00,AAA,1,PPP
2019/04/06 20:00,AAA,1,GO
2019/04/06 20:00,AAA,1,ON
2019/04/06 20:30,BBB,2,GO
2019/04/06 18:30,CCC,3,GO
2019/04/06 18:30,CCC,3,ON
2019/04/09 19:25,AAA,1 ON
2019/04/09 21:10,BBB,2,OFF
2019/04/09 17:55,CCC,3,OFF
2019/04/09 17:55,CCC,3,OFF

を持っています(date_master.csv)

この情報で、日付・ユーザ(user)ごとに最上位のレコードのみを抽出したいのですが、
ADODBからdistinctを指定して実行した場合に狙った結果が出力できません
(date3とu_idで重複排除を行いたいことが最終目標です)

出したい結果(logout.csv)
2019/04/06,20:00:00,AAA,1,PPP
2019/04/06,20:30:00,BBB,2,GO
2019/04/06,18:30:00,CCC,3,GO
2019/04/09,19:25:00,AAA,1 ON
2019/04/09,21:10:00,BBB,2,OFF
2019/04/09,17:55:00,CCC,3,OFF

objADO.Execute 
"SELECT distinct  Format([date3],'yyyy/mm/dd') AS date11,Format(([date3]),'hh:nn:ss') AS date12, user ,u_id , action INTO logout.csv " & _
" FROM date_master.csv ;"

同一の「date」でかつ同一の「u_id」の場合、最上位のレコードのみを残す
(2つ目以降のレコードを重複削除する)
方法は、どのようにすればよいのでしょうか?

別方法で対応を行おうとしています

考え方としては、
「重複排除の結果は、user(u_id)が変わっているので、userが変更された直後のデータのみを輩出する」
です。
以下のような感じをイメージして作成してみます

Do Until cv.AtEndOfStream
a = Split(cv.ReadLine, ",")
c = c + 1
ReDim Preserve d(3, c)
For i = 0 to 3
d(i, c) = a(i)
Next
Loop
cv.Close
Set cv = Nothing
Set cv = so.OpenTextFile(p & "\" & fa, 1)
t1 = cv.ReadLine
Set cr = so.OpenTextFile(p & "\" & fc, 2, True)
cr.WriteLine 
Do Until cv.AtEndOfStream
x = cv.ReadLine
a = Split(x, ",")
For i = 0 to c
If a(4) = d(1, i) Then
cr.WriteLine 
Exit For
End If
Next
Loop

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

0

「最上位のレコード」の定義を明確にする必要がありますね。

例えは、 action に PPP > GO > ON  > OFF というような順位があるとか。

これなら、SQLで可能です。

csvの行が上の方が上位だという定義だとしたら、ttyp03さんも言われてますが、SQLでは無理ですね。

コードでCSVファイルを先頭から1行ずつ読み込んで、重複は除外するということになります。
重複排除は、連想配列(Dictionaryオブジェクト)を使うとシンプルにできます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/11 15:44

    連想配列を使用を考えていたのですが、
    連想配列は、2つのカラムで同時(今回の場合、date3とuserの双方が一致)で重複排除ができるのでしょうか?

    キャンセル

  • 2019/04/11 19:31

    連想配列のキーは一つですが、2つのカラムを連結したものをキーにすれば可能です。
    date3 & ";" & u_id
    というように適当な区切り文字を挟んで連結したものをキーにします。

    キャンセル

  • 2019/04/12 09:10

    了解いたしました。
    ありがとうございます

    キャンセル

0

データベース(SQL)の概念として順番というものは存在しません。
(一般的な話であって該当しないDBもあるかもしれませんが)
SELECT時に明示的にORDER BYで順序を決定するものです。
なので、CSVファイルに対し、1行目を上位とするのであれば、SQLで抽出するのではなく、VBScriptのコードでCSVファイルを読み込み、日付とIDから除外するレコードを決定するべきです。
逆にSQLを使うのであれば、ORDER BYで論理的に順番を決定できる情報があるなら使用可能です。
今回のデータの場合、actionが名前の順というわけではないようですので、SQLではどうにもなりません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/11 14:11

    出力される処理は秒単位で出力されているが、csv上では分単位まで出力される仕様になっているため、csvの並びは変わらない状態ででます。
    この条件のため、最も遅い処理=csvの最上位処理で判断しようとしています

    キャンセル

  • 2019/04/11 14:12

    出力される処理=date3です

    キャンセル

  • 2019/04/11 14:35

    CSV上で並び順が保証されていても、SQLを通した場合にはその並び順は保証できないのでSQLで処理することはできない、という回答です。
    でももしかしたら「ADO経由でCSVを扱う場合のレコード順はファイル内の順序を保証している」という技術的資料があれば話は別です。
    x_xさんの回答のようにTOP 1などを使えばいけるかもしれませんが、ORDER BYしてしまうと保証はできなくなるのでお気をつけください。

    キャンセル

  • 2019/04/11 15:38

    了解しました。
    ありがとうございます

    キャンセル

0

TOP 1 を使えばとれるかも。
CSVのカンマ抜けを修正したうえで

    objADO.Execute _
    "SELECT distinct Format(a.date3,'yyyy/mm/dd') AS date11,Format((a.date3),'hh:nn:ss') AS date12, a.user , a.u_id , a.action INTO logout.csv " & _
    " FROM date_master.csv a WHERE a.action = (SELECT TOP 1 b.action FROM date_master.csv b WHERE Format(a.date3,'yyyy/mm/dd') = Format(b.date3,'yyyy/mm/dd') AND a.u_id = b.u_id)" & _
    " ORDER BY Format(a.date3,'yyyy/mm/dd'), a.u_id;"

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/11 15:36

    すいません
    ORDER BY Format(a.date3,'yyyy/mm/dd'), a.u_id;"
    のところでは、同時刻帯のレコードの並び順を決定できるように見えなかったので、WHERE a.action = (SELECT TOP 1 b.action FROM date_master.csv b WHERE Format(a.date3,'yyyy/mm/dd') = Format(b.date3,'yyyy/mm/dd') AND a.u_id = b.u_id)"
    のところで行っているのかと思いました。

    キャンセル

  • 2019/04/11 15:37

    >hatena19
    ありがとうございます。
    ご記載の方法でこちらでも確認してみます

    キャンセル

  • 2019/04/11 15:48

    サブクエリの
    (SELECT TOP 1 b.action FROM date_master.csv b WHERE Format(a.date3,'yyyy/mm/dd') = Format(b.date3,'yyyy/mm/dd') AND a.u_id = b.u_id)
    の部分で日付とu_idごとの先頭レコードを抽出していることになりますが、csvの場合、ORDER BY がないと1件のみの出力になるようです。
    Accessのテーブルで実験すると重複して出力されるので、csvの特性なのかもしれません。
    ただ、保証はないと思われますので、自分がするなら、SQLは使わないですね。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.60%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る