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

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

新規登録して質問してみよう
ただいま回答率
85.49%
VBScript

VBScript(Visual Basic Scripting Edition)はMicrosftが開発したスクリプト言語であり、Visual Basicのサブセットです。

Q&A

解決済

3回答

6294閲覧

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

amatsuno

総合スコア54

VBScript

VBScript(Visual Basic Scripting Edition)はMicrosftが開発したスクリプト言語であり、Visual Basicのサブセットです。

0グッド

0クリップ

投稿2019/04/09 08:27

編集2019/04/11 07:03

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

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

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

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

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

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

投稿2019/04/10 11:19

hatena19

総合スコア33692

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

amatsuno

2019/04/11 05:10

定義に関しては、まさに「csvの行が上の方が上位」となります (出力される処理は秒単位で出力されているが、csv上では分単位まで出力される仕様になっているため、csvの並びは変わらない状態ででます。この条件のため、最も遅い処理=csvの最上位処理で判断となっています)
amatsuno

2019/04/11 05:12

出力される処理=date3です
amatsuno

2019/04/11 06:44

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

2019/04/11 10:31

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

2019/04/12 00:10

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

0

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

VBScript

1 objADO.Execute _ 2 "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 " & _ 3 " 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)" & _ 4 " ORDER BY Format(a.date3,'yyyy/mm/dd'), a.u_id;"

投稿2019/04/10 01:58

x_x

総合スコア13749

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

amatsuno

2019/04/11 05:16

ご回答、ありがとうございます。 order by で指定している並び順が、csvの並び順で制御しているのは、where句の箇所で相違ないでしょうか?
x_x

2019/04/11 05:43

ちょっと何を言っているのかわかりません。 order by句は where句ではないです
hatena19

2019/04/11 05:58

Top 1 だと ORDER BY で指定したフィールドで、重複があると、重複したレコードも出力されます。必ず1件返すとは限らないので、使えないかと。
hatena19

2019/04/11 06:22

と思ったのですが、念のために実験してみたら、 ORDER BY を指定しないと、先頭の1件のみ返すようですね。 質問のデータでは希望の結果になってます。 そういう仕様なのか、たまたまなのかはわかりませんが。
amatsuno

2019/04/11 06: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)" のところで行っているのかと思いました。
amatsuno

2019/04/11 06:37

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

2019/04/11 06: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は使わないですね。
guest

0

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

投稿2019/04/09 23:44

ttyp03

総合スコア16998

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

amatsuno

2019/04/11 05:11

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

2019/04/11 05:12

出力される処理=date3です
ttyp03

2019/04/11 05:35

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

2019/04/11 06:38

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問